[
  {
    "path": ".gitignore",
    "content": "*~\n*.o\n*.lo\n*.la\nm4\n.deps\n.libs\n\n#\n# binaries\n#\nAC\nWTP\nWUA\n\n#\n# autoconf files\n#\nMakefile\nMakefile.in\naclocal.m4\nautom4te.cache/\ncompile\nconfig.guess\nconfig.h\nconfig.h.in\nconfig.log\nconfig.status\nconfig.sub\nconfigure\ndepcomp\ninstall-sh\nlibtool\nltmain.sh\nmissing\nstamp-h1\n"
  },
  {
    "path": "AC.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n#include \"CWCommon.h\"\n#include \"tap.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/*_________________________________________________________*/\n/*  *******************___VARIABLES___*******************  */\nCWThreadMutex gCreateIDMutex;\n\n/* array that stores per WTPs infos */\nCWWTPManager gWTPs[CW_MAX_WTP];\nCWThreadMutex gWTPsMutex;\n\nint gEnabledLog;\nint gMaxLogFileSize;\nchar gLogFileName[] = AC_LOG_FILE_NAME;\n\n/* number of active WTPs */\nint gActiveWTPs = 0;\nCWThreadMutex gActiveWTPsMutex;\n\n/* max WTPs */\nint gMaxWTPs;\n/* The Radio MAC Field of the discovery response */\nint gRMACField = 2;\n/* The Wireless Field of the discovery response */\nint gWirelessField = 0;\n/* DTLS Policy for data channel */\nint gDTLSPolicy = DTLS_ENABLED_DATA;\n/* special socket to handle multiple network interfaces */\nCWMultiHomedSocket gACSocket;\n/* AC's network interfaces */\nCWProtocolNetworkInterface *gInterfaces = NULL;\nint gInterfacesCount = 0;\n/* DTLS Context */\nCWSecurityContext gACSecurityContext;\nint gActiveStations = 0;\n/* max stations */\nint gLimit;\nchar **gMulticastGroups;\nint gMulticastGroupsCount;\nCWAuthSecurity gACDescriptorSecurity;\nint gACHWVersion;\nint gACSWVersion;\nchar *gACName = NULL;\n\nint gDiscoveryTimer = 20;\nint gEchoRequestTimer = CW_ECHO_INTERVAL_DEFAULT;\n/* PROVVISORIO: Il valore e' scelto a caso */\nint gIdleTimeout = 10;\n\n/*_________________________________________________________*/\n/*  *******************___FUNCTIONS___*******************  */\n\nvoid usage(void)\n{\n}\n\nint main(int argc, char * const argv[])\n{\n\tint run_daemon = 1;\n\tint c;\n\n#ifdef CW_DEBUGGING\n\tconst struct rlimit rlim = {\n\t\t.rlim_cur = RLIM_INFINITY,\n\t\t.rlim_max = RLIM_INFINITY\n\t};\n\n\t/* unlimited size for cores */\n\tsetrlimit(RLIMIT_CORE, &rlim);\n#endif\n\n\twhile (-1 != (c = getopt(argc, argv, \"hf\"))) {\n\t\tswitch(c) {\n\t\tcase 'h':\n\t\t\tusage();\n\t\t\texit(1);\n\t\t\tbreak;\n\n\t\tcase 'f':\n\t\t\trun_daemon = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tusage();\n\t\t\texit(1);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Daemon Mode */\n\tif (run_daemon)\n\t\tif (daemon(1, 0) != 0) {\n\t\t\tfprintf(stderr, \"daemon failed: %s\\n\", strerror(errno));\n\t\t\texit(1);\n\n\t\t}\n\n\tCWACInit();\n\tCWCreateConnectionWithHostapdAC();\n\tCWACEnterMainLoop();\n\tCWACDestroy();\n\tCWLogCloseFile();\n\n\treturn 0;\n}\n\nint CWACSemPostForOpenSSLHack(void *s)\n{\n\n\tCWThreadTimedSem *semPtr = (CWThreadTimedSem *) s;\n\n\tif (!CWThreadTimedSemIsZero(semPtr)) {\n\t\tCWLog(\"This Semaphore's Value should really be 0\");\n\t\t/* note: we can consider setting the value to 0 and going on,\n\t\t * that is what we do here\n\t\t */\n\t\tif (!CWErr(CWThreadTimedSemSetValue(semPtr, 0)))\n\t\t\treturn 0;\n\t}\n\n\tif (!CWErr(CWThreadTimedSemPost(semPtr))) {\n\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n\nvoid CWACInit()\n{\n\tint i;\n\tCWNetworkLev4Address *addresses = NULL;\n\tstruct sockaddr_in *IPv4Addresses = NULL;\n\n\tCWLogInitFile(AC_LOG_FILE_NAME);\n\n#ifndef CW_SINGLE_THREAD\n\tCWDebugLog(\"Use Threads\");\n#else\n\tCWDebugLog(\"Don't Use Threads\");\n#endif\n\n\tCWErrorHandlingInitLib();\n\n\tif (!CWParseSettingsFile()) {\n\t\tfprintf(stderr,\"Can't load AC settings file\\n\");\n\t\texit(1);\n\t}\n\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\tif (timer_init() == 0) {\n\t\tfprintf(stderr,\"Can't init timer module\\n\");\n\t\texit(1);\n\t}\n\n        if (!CWErr(CWParseConfigFile())) {\n                /* error starting */\n                fprintf(stderr,\"Can't load AC config file\\n\");\n                exit(1);\n        }\n\n        CWDebugLog(\"Starting AC\");\n        CWDebugLog(\"Waiting for WTPs to enter join state\");\n        sleep(CW_NEIGHBORDEAD_INTERVAL_DEFAULT+CW_ECHO_INTERVAL_DEFAULT);\n\n\tif (\n#ifndef CW_NO_DTLS\n\t    !CWErr(CWSecurityInitLib()) ||\n#endif\n\t    !CWErr(CWNetworkInitSocketServerMultiHomed\n\t\t   (&gACSocket, CW_CONTROL_PORT, gMulticastGroups, gMulticastGroupsCount))\n\t    || !CWErr(CWNetworkGetInterfaceAddresses(&gACSocket, &addresses, &IPv4Addresses))\n\t    || !CWErr(CWCreateThreadMutex(&gWTPsMutex)) || !CWErr(CWCreateThreadMutex(&gActiveWTPsMutex))) {\n\n\t\t/* error starting */\n\t\tCWLog(\"Can't start AC\");\n\t\texit(1);\n\t}\n#ifndef CW_NO_DTLS\n\tif (gACDescriptorSecurity == CW_X509_CERTIFICATE) {\n\n\t\tif (!CWErr(CWSecurityInitContext(&gACSecurityContext,\n\t\t\t\t\t\t \"root.pem\",\n\t\t\t\t\t\t \"server.pem\", \"prova\", CW_FALSE, CWACSemPostForOpenSSLHack))) {\n\n\t\t\tCWLog(\"Can't start AC\");\n\t\t\texit(1);\n\t\t}\n\t} else {\t\t/* preshared */\n\t\tif (!CWErr(CWSecurityInitContext(&gACSecurityContext,\n\t\t\t\t\t\t NULL, NULL, NULL, CW_FALSE, CWACSemPostForOpenSSLHack))) {\n\t\t\tCWLog(\"Can't start AC\");\n\t\t\texit(1);\n\t\t}\n\t}\n#endif\n\tCW_FREE_OBJECTS_ARRAY(gMulticastGroups, gMulticastGroupsCount);\n\n\tfor (i = 0; i < gMaxWTPs; i++) {\n\t\tgWTPs[i].isNotFree = CW_FALSE;\n\n\t\tif (!gWTPs[i].tap_fd) {\n\t\t\tinit_AC_tap_interface(i);\n\t\t}\n\n\t}\n\n\t/* store network interface's addresses */\n\tgInterfacesCount = CWNetworkCountInterfaceAddresses(&gACSocket);\n\tCWLog(\"Found %d Network Interface(s)\", gInterfacesCount);\n\n\tif (gInterfacesCount <= 0) {\n\t\tCWLog(\"Can't start AC\");\n\t\texit(1);\n\t}\n\n\tCW_CREATE_ARRAY_ERR(gInterfaces, gInterfacesCount, CWProtocolNetworkInterface, CWLog(\"Out of Memory\");\n\t\t\t    return;\n\t    );\n\n\tfor (i = 0; i < gInterfacesCount; i++) {\n\t\tgInterfaces[i].WTPCount = 0;\n\t\tCW_COPY_NET_ADDR_PTR(&(gInterfaces[i].addr), ((CWNetworkLev4Address *) & ((addresses)[i])));\n\t\tif (IPv4Addresses != NULL) {\n\t\t\tCW_COPY_NET_ADDR_PTR(&(gInterfaces[i].addrIPv4), &((IPv4Addresses)[i]));\n\t\t}\n\t}\n\tCW_FREE_OBJECT(addresses);\n\tCW_FREE_OBJECT(IPv4Addresses);\n\n\tif (!CWErr(CWCreateThreadMutex(&gCreateIDMutex))) {\n\t\texit(1);\n\t}\n\n\tCWLog(\"AC Started\");\n}\n\nvoid CWCreateConnectionWithHostapdAC()\n{\n\n\tCWThread thread_ipc_with_ac_hostapd;\n\tif (!CWErr(CWCreateThread(&thread_ipc_with_ac_hostapd, CWACipc_with_ac_hostapd, NULL))) {\n\t\tCWLog(\"Error starting Thread that receive command and 802.11 frame from hostapd (WTP side)\");\n\t\texit(1);\n\t}\n\n}\n\nvoid CWACDestroy()\n{\n\n\tCWNetworkCloseMultiHomedSocket(&gACSocket);\n\n\t/*\n\t   for(i = 0; i < CW_MAX_WTP; i++) {\n\t   //CW_FREE_OBJECT(gWTPs[i].addr);\n\t   }\n\t */\n\n#ifndef CW_NO_DTLS\n\tCWSslCleanUp();\n#endif\n\n\tCWDestroyThreadMutex(&gWTPsMutex);\n\tCWDestroyThreadMutex(&gCreateIDMutex);\n\tCWDestroyThreadMutex(&gActiveWTPsMutex);\n\n\tCW_FREE_OBJECT(gACName);\n\tCW_FREE_OBJECT(gInterfaces);\n\n\tCWLog(\"AC Destroyed\");\n}\n\nunsigned int CWGetSeqNum()\n{\n\n\tstatic unsigned int seqNum = 0;\n\tunsigned int r;\n\n\tif (!CWThreadMutexLock(&gCreateIDMutex)) {\n\n\t\tCWDebugLog(\"Error Locking a mutex\");\n\t}\n\n\tr = seqNum;\n\n\tif (seqNum == CW_MAX_SEQ_NUM)\n\t\tseqNum = 0;\n\telse\n\t\tseqNum++;\n\n\tCWThreadMutexUnlock(&gCreateIDMutex);\n\treturn r;\n}\n\nint CWGetFragmentID()\n{\n\n\tstatic int fragID = 0;\n\tint r;\n\n\tif (!CWThreadMutexLock(&gCreateIDMutex)) {\n\n\t\tCWDebugLog(\"Error Locking a mutex\");\n\t}\n\n\tr = fragID;\n\n\tif (fragID == CW_MAX_FRAGMENT_ID)\n\t\tfragID = 0;\n\telse\n\t\tfragID++;\n\n\tCWThreadMutexUnlock(&gCreateIDMutex);\n\treturn r;\n}\n"
  },
  {
    "path": "ACAppsProtocol.h",
    "content": "/*\n *  appsToAcProtocol.h\n *\n *\n *  Created by Antonio Davoli on 03/03/09.\n *  Copyright 2009 La Sapienza. All rights reserved.\n *\n */\n\n/* Macro Definition */\n\n/* AC Request Message */\n\n/****************************************\n *  For LIST, QUIT (without argument)   *\n *                                      *\n *      0               7               *\n *      +-+-+-+-+-+-+-+-+               *\n *      |    Cmd_msg    |               *\n *      +-+-+-+-+-+-+-+-+               *\n *                                      *\n ****************************************/\n\n/* CMD_MSG Types */\n\n#define FULL_CLIENT_CONNECTED -1\n#define CONNECTION_OK 1\n#define QUIT_MSG 0\n#define LIST_MSG 1\n#define CONF_UPDATE_MSG 2\n\n/********************************************************************************************************************************\n * List Response Message:                                                                                                       *\n *                                                                                                                              *\n *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   *\n *  |   Active#   |    WTP_ID 1   | NameLength 1  |   WTP Name 1    | ... |    WTP ID N   | NameLength N  |   WTP Name N    |   *\n *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   *\n *                                                                                                                              *\n *  where N is equal to Active# (Number of Active WTPs)                                                                         *\n ********************************************************************************************************************************/\n\n/********************************************************************************************************\n * For CONF_UPDATE_MSG type:                                                                            *\n *                                                                                                      *\n *      0              7               15              23                                    X          *\n *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+         *\n *      |    cmd_msg    |    msg_elem   |   WPT Index   |       Message Specific Payload      |         *\n *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+         *\n *                                                                                                      *\n ********************************************************************************************************/\n\n#define PAYLOAD_START ((sizeof(unsigned char)*2) + sizeof(int))\n#define ALL_ACTIVE_WTPS -1\n\n#define MSG_ELEMENT_TYPE_OFDM 1\n#define MSG_ELEMENT_TYPE_VENDOR_UCI 2\n#define MSG_ELEMENT_TYPE_VENDOR_WUM 3\n\n/****************************************************************************************\n * Message Specific Payload for MSG_ELEMENT_TYPE_OFDM TYPE (802.11 Binding Version)     *\n *                                                                                      *\n *      0                   1                   2                   3                   *\n *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1                 *\n *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               *\n *      |    Radio ID   |    Reserved   | Current Chan  |  Band Support |               *\n *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               *\n *      |                         TI Threshold                          |               *\n *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               *\n *                                                                                      *\n ****************************************************************************************/\n\n/* Radio ID is filled in the creation message funcion (inside the AC) */\n"
  },
  {
    "path": "ACBinding.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A              *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Daniele De Sanctis (danieledesanctis@gmail.com)                                    *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool CWACInitBinding(int i)\n{\n\tint j;\n\tbindingValues *aux;\n\n\tCW_CREATE_OBJECT_ERR(aux, bindingValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t(gWTPs[i].WTPProtocolManager).bindingValuesPtr = (void *)aux;\n\n\tCW_CREATE_ARRAY_ERR(aux->qosValues, NUM_QOS_PROFILES, WTPQosValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t//Init default values\n\tfor (j = 0; j < NUM_QOS_PROFILES; j++) {\n\t\taux->qosValues[j].cwMin = gDefaultQosValues[j].cwMin;\n\t\taux->qosValues[j].cwMax = gDefaultQosValues[j].cwMax;\n\t\taux->qosValues[j].AIFS = gDefaultQosValues[j].AIFS;\n\n\t\taux->qosValues[j].queueDepth = 0;\n\t\taux->qosValues[j].dot1PTag = 0;\n\t\taux->qosValues[j].DSCPTag = 0;\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWMergeQosValues(int WTPIndex)\n{\n\tint i;\n\tbindingValues *aux;\n\n\taux = (bindingValues *) (gWTPs[WTPIndex].WTPProtocolManager).bindingValuesPtr;\n\n\tfor (i = 0; i < NUM_QOS_PROFILES; i++) {\n\t\tif (gWTPs[WTPIndex].qosValues[i].cwMin == UNUSED_QOS_VALUE) {\n\t\t\tgWTPs[WTPIndex].qosValues[i].cwMin = aux->qosValues[i].cwMin;\n\t\t}\n\n\t\tif (gWTPs[WTPIndex].qosValues[i].cwMax == UNUSED_QOS_VALUE) {\n\t\t\tgWTPs[WTPIndex].qosValues[i].cwMax = aux->qosValues[i].cwMax;\n\t\t}\n\n\t\tif (gWTPs[WTPIndex].qosValues[i].AIFS == UNUSED_QOS_VALUE) {\n\t\t\tgWTPs[WTPIndex].qosValues[i].AIFS = aux->qosValues[i].AIFS;\n\t\t}\n\t}\n\treturn CW_TRUE;\n}\n\n/******************************************************************\n * 2009 Updates:                                                  *\n *              Functions for management of Configuration Update  *\n *              Request with OFDM Message Element                 *\n ******************************************************************/\n\nCWBool CWMergeOFDMValues(int WTPIndex)\n{\n\n\tOFDMControlValues *aux;\n\n\taux = (OFDMControlValues *) (gWTPs[WTPIndex].WTPProtocolManager).bindingValuesPtr;\n\n\tif (gWTPs[WTPIndex].ofdmValues->currentChan == UNUSED_OFDM_VALUE)\n\t\tgWTPs[WTPIndex].ofdmValues->currentChan = aux->currentChan;\n\n\tif (gWTPs[WTPIndex].ofdmValues->BandSupport == UNUSED_OFDM_VALUE)\n\t\tgWTPs[WTPIndex].ofdmValues->BandSupport = aux->BandSupport;\n\n\tif (gWTPs[WTPIndex].ofdmValues->TIThreshold == UNUSED_OFDM_VALUE)\n\t\tgWTPs[WTPIndex].ofdmValues->TIThreshold = aux->TIThreshold;\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleWTPOFDM(CWProtocolMessage * msgPtr, int radioID)\n{\n\tconst int totalMessageLength = BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL_LENGTH;\n\tint *iPtr;\n\tOFDMControlValues *valuesPtr;\n\n\tCWLog(\"Assembling Binding Configuration Update Request [OFDM CASE]...\");\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!CWMergeOFDMValues(*iPtr)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tvaluesPtr = gWTPs[*iPtr].ofdmValues;\n\n\t/* create message */\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, totalMessageLength, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, radioID);\n\tCWProtocolStore32(msgPtr, valuesPtr->currentChan);\n\tCWProtocolStore8(msgPtr, valuesPtr->BandSupport);\n\tCWProtocolStore32(msgPtr, valuesPtr->TIThreshold);\n\n\tCWLog(\"Assembling Binding Configuration Update Request [OFDM CASE]: Message Assembled.\");\n\n\treturn CWAssembleMsgElem(msgPtr, BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL);\n}\n\nCWBool CWAssembleWTPQoS(CWProtocolMessage * msgPtr, int radioID, int tagPackets)\n{\n\tconst int headerLength = 2;\n\tconst int messageBodyLength = 32;\n\tconst int totalMessageLength = headerLength + messageBodyLength;\n\tint i;\n\tint *iPtr;\n\tWTPQosValues *valuesPtr;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\tif (!CWMergeQosValues(*iPtr)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tvaluesPtr = gWTPs[*iPtr].qosValues;\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, totalMessageLength, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, radioID);\n\tCWProtocolStore8(msgPtr, tagPackets);\n\n\tfor (i = 0; i < NUM_QOS_PROFILES; i++) {\n\t\tCWProtocolStore8(msgPtr, valuesPtr[i].queueDepth);\n\t\tCWProtocolStore16(msgPtr, valuesPtr[i].cwMin);\n\t\tCWProtocolStore16(msgPtr, valuesPtr[i].cwMax);\n\t\tCWProtocolStore8(msgPtr, valuesPtr[i].AIFS);\n\t\tCWProtocolStore8(msgPtr, valuesPtr[i].dot1PTag);\n\t\tCWProtocolStore8(msgPtr, valuesPtr[i].DSCPTag);\n\t}\n\n\treturn CWAssembleMsgElem(msgPtr, BINDING_MSG_ELEMENT_TYPE_WTP_QOS);\n}\n\nCWBool CWBindingAssembleConfigureResponse(CWProtocolMessage ** msgElems, int *msgElemCountPtr)\n{\n\tCWWTPRadiosInfo radiosInfo;\n\tint *iPtr;\n\tconst int tagPackets = 0;\n\tint k = -1, radioCount, radioID, j;\n\n\tif (msgElems == NULL || msgElemCountPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\t//Calculate the number of msg Elements\n\t*msgElemCountPtr = 0;\n\tradiosInfo = gWTPs[*iPtr].WTPProtocolManager.radiosInfo;\n\tradioCount = radiosInfo.radioCount;\n\t*msgElemCountPtr = radioCount;\n\n\tCWLog(\"Assembling Binding Configuration Response...\");\n\n\t//Reserve memory for msg Elements\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(*msgElems, *msgElemCountPtr, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!CWThreadMutexLock(&(gWTPs[*iPtr].interfaceMutex))) {\n\t\tCWLog(\"Error locking a mutex\");\n\t\tCWCloseThread();\n\t}\n\t//Fill gWTPs[*iPtr].qosValues with default settings\n\tgWTPs[*iPtr].qosValues = gDefaultQosValues;\n\n\tfor (j = 0; j < radioCount; j++) {\n\t\tradioID = radiosInfo.radiosInfo[j].radioID;\n\t\t// Assemble WTP QoS Message Element for each radio\n\t\tif (!(CWAssembleWTPQoS(&(*msgElems[++k]), radioID, tagPackets))) {\n\t\t\tint i;\n\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*msgElems[i]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(*msgElems);\n\t\t\tCWThreadMutexUnlock(&(gWTPs[*iPtr].interfaceMutex));\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\t}\n\n\tgWTPs[*iPtr].qosValues = NULL;\n\tCWThreadMutexUnlock(&(gWTPs[*iPtr].interfaceMutex));\n\n\tCWLog(\"Binding Configuration Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\n/******************************************************************\n * 2009 Updates:                                                  *\n *              Added new switch case for ofdm message management *\n ******************************************************************/\n\nCWBool CWBindingAssembleConfigurationUpdateRequest(CWProtocolMessage ** msgElems, int *msgElemCountPtr,\n\t\t\t\t\t\t   int BindingMsgElement)\n{\n\tCWWTPRadiosInfo radiosInfo;\n\tint *iPtr;\n\tconst int tagPackets = 0;\n\tint k = -1, radioCount, radioID, j;\n\n\tif (msgElems == NULL || msgElemCountPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\n\t*msgElemCountPtr = 0;\n\n\tradiosInfo = gWTPs[*iPtr].WTPProtocolManager.radiosInfo;\n\tradioCount = radiosInfo.radioCount;\n\t*msgElemCountPtr = radioCount;\n\n\tCWLog(\"Assembling Binding Configuration Update Request...\");\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(*msgElems, *msgElemCountPtr, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/* Selection of type of Conf Update Request */\n\n\tswitch (BindingMsgElement) {\n\tcase BINDING_MSG_ELEMENT_TYPE_WTP_QOS:{\n\t\t\tfor (j = 0; j < radioCount; j++) {\n\t\t\t\tradioID = radiosInfo.radiosInfo[j].radioID;\n\n\t\t\t\t// Assemble Message Elements\n\t\t\t\tif (!(CWAssembleWTPQoS(&(*msgElems[++k]), radioID, tagPackets))) {\n\t\t\t\t\tint i;\n\t\t\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*msgElems[i]);\n\t\t\t\t\t}\n\t\t\t\t\tCW_FREE_OBJECT(*msgElems);\n\t\t\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\tcase BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL:{\n\t\t\tfor (j = 0; j < radioCount; j++) {\n\t\t\t\tradioID = radiosInfo.radiosInfo[j].radioID;\n\n\t\t\t\t/* Assemble Message Elements */\n\t\t\t\tif (!(CWAssembleWTPOFDM(&(*msgElems[++k]), radioID))) {\n\t\t\t\t\tint i;\n\t\t\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*msgElems[i]);\n\t\t\t\t\t}\n\t\t\t\t\tCW_FREE_OBJECT(*msgElems);\n\t\t\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\tdefault:{\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\t}\n\n\tCWLog(\"Binding Configuration Update Request Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWBindingSaveConfigurationUpdateResponse(CWProtocolResultCode resultCode, int WTPIndex)\n{\n\tint i;\n\n\tbindingValues *aux = (bindingValues *) gWTPs[WTPIndex].WTPProtocolManager.bindingValuesPtr;\n\n\tif (resultCode == CW_PROTOCOL_SUCCESS) {\n\t\tif (gWTPs[WTPIndex].qosValues != NULL) {\n\t\t\tfor (i = 0; i < NUM_QOS_PROFILES; i++) {\n\t\t\t\taux->qosValues[i].cwMin = gWTPs[WTPIndex].qosValues[i].cwMin;\n\t\t\t\taux->qosValues[i].cwMax = gWTPs[WTPIndex].qosValues[i].cwMax;\n\t\t\t\taux->qosValues[i].AIFS = gWTPs[WTPIndex].qosValues[i].AIFS;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACBinding.h",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A              *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#ifndef __CAPWAP_ACBinding_HEADER__\n#define __CAPWAP_ACBinding_HEADER__\n\nCWBool CWACInitBinding(int i);\nCWBool CWBindingAssembleConfigureResponse(CWProtocolMessage ** msgElems, int *msgElemCountPtr);\n/****************************************************\n * 2009 Update:                                     *\n * The field BindingMsgElement has been added for   *\n * the multiple type of Message Element.            *\n ****************************************************/\nCWBool CWBindingAssembleConfigurationUpdateRequest(CWProtocolMessage ** msgElems, int *msgElemCountPtr,\n\t\t\t\t\t\t   int BindingMsgElement);\nCWBool CWBindingSaveConfigurationUpdateResponse(CWProtocolResultCode resultCode, int WTPIndex);\n\n#endif\n"
  },
  {
    "path": "ACConfigFile.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nconst char *CW_CONFIG_FILE = \"/etc/capwap/config.ac\";\n\nCWBool CWConfigFileInitLib()\n{\n\n\tgConfigValuesCount = 11;\n\n\tCW_CREATE_ARRAY_ERR(gConfigValues,\n\t\t\t    gConfigValuesCount, CWConfigValue, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tgConfigValues[0].type = CW_INTEGER;\n\tgConfigValues[0].code = \"</AC_HW_VERSION>\";\n\tgConfigValues[0].value.int_value = 0;\n\n\tgConfigValues[1].type = CW_INTEGER;\n\tgConfigValues[1].code = \"</AC_SW_VERSION>\";\n\tgConfigValues[1].value.int_value = 0;\n\n\tgConfigValues[2].type = CW_INTEGER;\n\tgConfigValues[2].code = \"</AC_MAX_STATIONS>\";\n\tgConfigValues[2].value.int_value = 0;\n\n\tgConfigValues[3].type = CW_INTEGER;\n\tgConfigValues[3].code = \"</AC_MAX_WTPS>\";\n\tgConfigValues[3].value.int_value = 0;\n\n\tgConfigValues[4].type = CW_STRING;\n\tgConfigValues[4].code = \"</AC_SECURITY>\";\n\tgConfigValues[4].value.str_value = NULL;\n\n\tgConfigValues[5].type = CW_STRING;\n\tgConfigValues[5].code = \"</AC_NAME>\";\n\tgConfigValues[5].value.str_value = NULL;\n\n\tgConfigValues[6].type = CW_STRING_ARRAY;\n\tgConfigValues[6].code = \"<AC_MCAST_GROUPS>\";\n\tgConfigValues[6].endCode = \"</AC_MCAST_GROUPS>\";\n\tgConfigValues[6].value.str_array_value = NULL;\n\tgConfigValues[6].count = 0;\n\n\tgConfigValues[7].type = CW_INTEGER;\n\tgConfigValues[7].code = \"</AC_FORCE_MTU>\";\n\tgConfigValues[7].value.int_value = 0;\n\n\tgConfigValues[8].type = CW_STRING;\n\tgConfigValues[8].code = \"</AC_LEV3_PROTOCOL>\";\n\tgConfigValues[8].value.str_value = NULL;\n\n\tgConfigValues[9].type = CW_INTEGER;\n\tgConfigValues[9].code = \"</AC_LOG_FILE_ENABLE>\";\n\tgConfigValues[9].value.int_value = 0;\n\n\tgConfigValues[10].type = CW_INTEGER;\n\tgConfigValues[10].code = \"</AC_LOG_FILE_SIZE>\";\n\tgConfigValues[10].value.int_value = DEFAULT_LOG_SIZE;\n\n\treturn CW_TRUE;\n}\n\nCWBool CWConfigFileDestroyLib()\n{\n\n\tint i;\n\n\t/* save the preferences we read */\n\tgACHWVersion = gConfigValues[0].value.int_value;\n\tgACSWVersion = gConfigValues[1].value.int_value;\n\tgLimit = gConfigValues[2].value.int_value;\n\tgMaxWTPs = gConfigValues[3].value.int_value;\n\n#ifndef CW_NO_DTLS\n\tif (gConfigValues[4].value.str_value != NULL && !strcmp(gConfigValues[4].value.str_value, \"PRESHARED\")) {\n\t\tgACDescriptorSecurity = CW_PRESHARED;\n\t} else {\n\t\t/* default */\n\t\tgACDescriptorSecurity = CW_X509_CERTIFICATE;\n\t}\n#endif\n\n\tif (gConfigValues[5].value.str_value != NULL) {\n\n\t\tCW_CREATE_STRING_FROM_STRING_ERR(gACName,\n\t\t\t\t\t\t (gConfigValues[5].value.str_value),\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\t//CW_FREE_OBJECT(gACName);\n\t}\n\n\t/* avoid to allocate 0 bytes */\n\tif (gConfigValues[6].count) {\n\n\t\tCW_CREATE_ARRAY_ERR(gMulticastGroups, gConfigValues[6].count, char *,\n\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tfor (i = 0; i < gConfigValues[6].count; i++) {\n\n\t\t\tCW_CREATE_STRING_FROM_STRING_ERR(gMulticastGroups[i],\n\t\t\t\t\t\t\t (gConfigValues[6].value.str_array_value)[i],\n\t\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t}\n\t}\n\n\tgMulticastGroupsCount = gConfigValues[6].count;\n\tCW_PRINT_STRING_ARRAY(gMulticastGroups, gMulticastGroupsCount);\n\n\tgCWForceMTU = gConfigValues[7].value.int_value;\n\n\tif (gConfigValues[8].value.str_value != NULL && !strcmp(gConfigValues[8].value.str_value, \"IPv6\")) {\n\n\t\tgNetworkPreferredFamily = CW_IPv6;\n\t} else {\n\t\t/* default */\n\t\tgNetworkPreferredFamily = CW_IPv4;\n\t}\n\n\tfor (i = 0; i < gConfigValuesCount; i++) {\n\t\tif (gConfigValues[i].type == CW_STRING) {\n\t\t\tCW_FREE_OBJECT(gConfigValues[i].value.str_value);\n\t\t} else if (gConfigValues[i].type == CW_STRING_ARRAY) {\n\t\t\tCW_FREE_OBJECTS_ARRAY((gConfigValues[i].value.str_array_value), gConfigValues[i].count);\n\t\t}\n\t}\n\n\tgEnabledLog = gConfigValues[9].value.int_value;\n\tgMaxLogFileSize = gConfigValues[10].value.int_value;\n\n\tCW_FREE_OBJECT(gConfigValues);\n\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACConfigureState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nint gCWChangeStatePendingTimer = CW_CHANGE_STATE_INTERVAL_DEFAULT;\n\nCWBool CWAssembleConfigureResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum);\n\nCWBool CWParseConfigureRequestMessage(unsigned char *msg,\n\t\t\t\t      int len,\n\t\t\t\t      int *seqNumPtr,\n\t\t\t\t      CWProtocolConfigureRequestValues * valuesPtr, unsigned char *, unsigned char *, char *, int);\n\nCWBool CWSaveConfigureRequestMessage(CWProtocolConfigureRequestValues * configureRequest,\n\t\t\t\t     CWWTPProtocolManager * WTPProtocolManager);\n\nCWBool ACEnterConfigure(int WTPIndex, CWProtocolMessage * msgPtr)\n{\n\n\t/*** tmp Radio Info ***/\n\tunsigned char tmp_RadioInformationABGN;\n\tunsigned char tmp_SuppRates[8];\n\tchar tmp_MultiDomCapa[6];\n\n\tint seqNum;\n\tCWProtocolConfigureRequestValues configureRequest;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"######### Configure State #########\");\n\n\tif (!(CWParseConfigureRequestMessage(msgPtr->msg,\n\t\t\t\t\t     msgPtr->offset,\n\t\t\t\t\t     &seqNum,\n\t\t\t\t\t     &configureRequest,\n\t\t\t\t\t     &tmp_RadioInformationABGN, tmp_SuppRates, tmp_MultiDomCapa, WTPIndex))) {\n\t\t/* note: we can kill our thread in case of out-of-memory\n\t\t * error to free some space.\n\t\t * we can see this just calling CWErrorGetLastErrorCode()\n\t\t */\n\t\treturn CW_FALSE;\n\t}\n\n\tCWLog(\"Configure Request Received\");\n\n\tif (!(CWSaveConfigureRequestMessage(&configureRequest, &(gWTPs[WTPIndex].WTPProtocolManager)))) {\n\t\treturn CW_FALSE;\n\t}\n\n\t/* Store Radio Info in gWTPs */\n\tgWTPs[WTPIndex].RadioInformationABGN = tmp_RadioInformationABGN;\n\tmemcpy(gWTPs[WTPIndex].SuppRates, tmp_SuppRates, 8);\n\tmemcpy(gWTPs[WTPIndex].MultiDomCapa, tmp_MultiDomCapa, 6);\n\n\t/* Store Radio Info in gWTPs */\n\n\tif (!(CWAssembleConfigureResponse(&(gWTPs[WTPIndex].messages),\n\t\t\t\t\t  &(gWTPs[WTPIndex].messagesCount), gWTPs[WTPIndex].pathMTU, seqNum))) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!CWACSendFragments(WTPIndex)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCWLog(\"Configure Response Sent\");\n\n\t/* start Change State Pending timer */\n\tif (!CWErr(CWTimerRequest(gCWChangeStatePendingTimer,\n\t\t\t\t  &(gWTPs[WTPIndex].thread),\n\t\t\t\t  &(gWTPs[WTPIndex].currentTimer), CW_CRITICAL_TIMER_EXPIRED_SIGNAL))) {\n\n\t\tCWCloseThread();\n\t}\n\n\tgWTPs[WTPIndex].currentState = CW_ENTER_DATA_CHECK;\n\treturn CW_TRUE;\n}\n\nCWBool CWParseConfigureRequestMessage(unsigned char *msg,\n\t\t\t\t      int len,\n\t\t\t\t      int *seqNumPtr,\n\t\t\t\t      CWProtocolConfigureRequestValues * valuesPtr,\n\t\t\t\t      unsigned char *tmp_RadioInformationABGN, unsigned char *tmp_SuppRates, char *tmp_MultiDomCapa, int WTPIndex)\n{\n\n\tCWControlHeaderValues controlVal;\n\tint i, j;\n\tint offsetTillMessages;\n\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL || seqNumPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Parsing Configure Request...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\t/* will be handled by the caller */\n\t\treturn CW_FALSE;\n\n\t/* Join Request in Configure state - WTP might have been restarted */\n\n        if (controlVal.messageTypeValue == CW_MSG_TYPE_VALUE_JOIN_REQUEST ){\n\t\tgWTPs[WTPIndex].currentState = CW_ENTER_JOIN;\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n                                    \"Message is Join Request in Configure State - switching state\");\n\t}\n\t\n        /* different type */\n\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_CONFIGURE_REQUEST)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t    \"Message is not Configure Request (maybe it is Image Data Request)\");\n\n\t*seqNumPtr = controlVal.seqNum;\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\toffsetTillMessages = completeMsg.offset;\n\n\t/* valuesPtr->WTPRadioInfo.radiosCount=0; */\n\tvaluesPtr->ACinWTP.count = 0;\n\tvaluesPtr->radioAdminInfoCount = 0;\n\n\t/* parse message elements */\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\n\t\tunsigned short int elemType = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int elemLen = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\t/*CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen); */\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_AC_NAME_CW_TYPE:\n\t\t\tif (!(CWParseACName(&completeMsg, elemLen, &(valuesPtr->ACName))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_AC_NAME_INDEX_CW_TYPE:\n\t\t\t/* just count how many radios we have,\n\t\t\t * so we can allocate the array\n\t\t\t */\n\t\t\tvaluesPtr->ACinWTP.count++;\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_RADIO_ADMIN_STATE_CW_TYPE:\n\t\t\t/* just count how many radios we have,\n\t\t\t * so we can allocate the array\n\t\t\t */\n\t\t\t(valuesPtr->radioAdminInfoCount)++;\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_STATISTICS_TIMER_CW_TYPE:\n\t\t\tif (!(CWParseWTPStatisticsTimer(&completeMsg, elemLen, &(valuesPtr->StatisticsTimer))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_REBOOT_STATISTICS_CW_TYPE:\n\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->WTPRebootStatistics,\n\t\t\t\t\t     WTPRebootStatisticsInfo, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tif (!(CWParseWTPRebootStatistics(&completeMsg, elemLen, valuesPtr->WTPRebootStatistics)))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE:\n\t\t\tif (!(CWParseWTPRadioInformation(&completeMsg, elemLen, tmp_RadioInformationABGN)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_IEEE80211_MULTI_DOMAIN_CAPABILITY_CW_TYPE:\n\t\t\tif (!(CWParseWTPMultiDomainCapability(&completeMsg, elemLen, tmp_MultiDomCapa)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_IEEE80211_SUPPORTED_RATES_CW_TYPE:\n\t\t\tif (!(CWParseWTPSupportedRates(&completeMsg, elemLen, tmp_SuppRates)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\t/* actually read each radio info */\n\tCW_CREATE_ARRAY_ERR((valuesPtr->ACinWTP).ACNameIndex,\n\t\t\t    (valuesPtr->ACinWTP).count,\n\t\t\t    CWACNameWithIndexValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCW_CREATE_ARRAY_ERR(valuesPtr->radioAdminInfo,\n\t\t\t    valuesPtr->radioAdminInfoCount,\n\t\t\t    CWRadioAdminInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\ti = 0;\n\tj = 0;\n\n\tcompleteMsg.offset = offsetTillMessages;\n\twhile (completeMsg.offset - offsetTillMessages < controlVal.msgElemsLen) {\n\t\tunsigned short int type = 0;\n\t\tunsigned short int len = 0;\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_AC_NAME_INDEX_CW_TYPE:\n\t\t\tif (!(CWParseACNameWithIndex(&completeMsg, len, &(valuesPtr->ACinWTP.ACNameIndex[i]))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\ti++;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_RADIO_ADMIN_STATE_CW_TYPE:\n\t\t\tif (!(CWParseWTPRadioAdminState(&completeMsg, len, &(valuesPtr->radioAdminInfo[j]))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tj++;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\t}\n\t}\n\tCWDebugLog(\"Configure Request Parsed\");\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleConfigureResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int MsgElemCount = 6;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Assembling Configure Response...\");\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, MsgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/* Assemble Message Elements */\n\tif ((!(CWAssembleMsgElemACIPv4List(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemACIPv6List(&(msgElems[++k])))) || (!(CWAssembleMsgElemCWTimer(&(msgElems[++k])))) ||\n\t    /*(!(CWAssembleMsgElemRadioOperationalState(-1, &(msgElems[++k])))) || */\n\t    (!(CWAssembleMsgElemDecryptErrorReportPeriod(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemIdleTimeout(&(msgElems[++k])))) || (!(CWAssembleMsgElemWTPFallback(&(msgElems[++k]))))\n\t    ) {\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\t/* error will be handled by the caller */\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!CWBindingAssembleConfigureResponse(&msgElemsBinding, &msgElemBindingCount)) {\n\t\tint i;\n\t\tfor (i = 0; i <= MsgElemCount; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\n\t}\n\n\t/*CWDebugLog(\"~~~~~ msg count: %d \", msgElemBindingCount); */\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CONFIGURE_RESPONSE,\n\t\t\t\tmsgElems, MsgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWDebugLog(\"Configure Response Assembled\");\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveConfigureRequestMessage(CWProtocolConfigureRequestValues * configureRequest,\n\t\t\t\t     CWWTPProtocolManager * WTPProtocolManager)\n{\n\n\tCWDebugLog(\"Saving Configure Request...\");\n\n\tCW_FREE_OBJECT(WTPProtocolManager->ACName);\n\n\tif ((configureRequest->ACName) != NULL)\n\t\tWTPProtocolManager->ACName = configureRequest->ACName;\n\n\tCW_FREE_OBJECT((WTPProtocolManager->ACNameIndex).ACNameIndex);\n\tWTPProtocolManager->ACNameIndex = configureRequest->ACinWTP;\n\n\tCW_FREE_OBJECT((WTPProtocolManager->radioAdminInfo).radios);\n\t(WTPProtocolManager->radioAdminInfo).radiosCount = configureRequest->radioAdminInfoCount;\n\t(WTPProtocolManager->radioAdminInfo).radios = configureRequest->radioAdminInfo;\n\n\tWTPProtocolManager->StatisticsTimer = configureRequest->StatisticsTimer;\n\n\t/*\n\t   CW_FREE_OBJECT((WTPProtocolManager->WTPRadioInfo).radios);\n\t   WTPProtocolManager->WTPRadioInfo = configureRequest->WTPRadioInfo;\n\t */\n\n\tCW_FREE_OBJECT(WTPProtocolManager->WTPRebootStatistics);\n\tWTPProtocolManager->WTPRebootStatistics = configureRequest->WTPRebootStatistics;\n\n\tCWDebugLog(\"Configure Request Saved\");\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACDataCheckState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool ACEnterDataCheck(int WTPIndex, CWProtocolMessage * msgPtr)\n{\n\n\t/*CWProtocolMessage *messages = NULL; */\n\tint seqNum;\n\tCWProtocolChangeStateEventRequestValues *changeStateEvent;\n\n\tCWLog(\"\\n\");\n\tCWDebugLog(\"######### Status Event #########\");\n\n\t/* Destroy ChangeStatePending timer */\n\tif (!CWErr(CWTimerCancel(&(gWTPs[WTPIndex].currentTimer)))) {\n\n\t\tCWCloseThread();\n\t}\n\n\tCW_CREATE_OBJECT_ERR(changeStateEvent,\n\t\t\t     CWProtocolChangeStateEventRequestValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!(CWParseChangeStateEventRequestMessage(msgPtr->msg, msgPtr->offset, &seqNum, changeStateEvent))) {\n\t\t/* note: we can kill our thread in case of out-of-memory\n\t\t * error to free some space.\n\t\t * we can see this just calling CWErrorGetLastErrorCode()\n\t\t */\n\t\treturn CW_FALSE;\n\t}\n\n\tCWLog(\"Change State Event Received\");\n\n\tif (!(CWSaveChangeStateEventRequestMessage(changeStateEvent, &(gWTPs[WTPIndex].WTPProtocolManager))))\n\t\treturn CW_FALSE;\n\n\tif (!(CWAssembleChangeStateEventResponse(&(gWTPs[WTPIndex].messages),\n\t\t\t\t\t\t &(gWTPs[WTPIndex].messagesCount), gWTPs[WTPIndex].pathMTU, seqNum))) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!CWACSendFragments(WTPIndex)) {\n\n\t\treturn CW_FALSE;\n\t}\n\n\t/* Start NeighbourDeadInterval timer */\n\tif (!CWErr(CWTimerRequest(gCWNeighborDeadInterval,\n\t\t\t\t  &(gWTPs[WTPIndex].thread),\n\t\t\t\t  &(gWTPs[WTPIndex].currentTimer), CW_CRITICAL_TIMER_EXPIRED_SIGNAL))) {\n\n\t\tCWCloseThread();\n\t}\n\n\tCWLog(\"Change State Event Response Sent\");\n\n\tgWTPs[WTPIndex].currentState = CW_ENTER_RUN;\n\tgWTPs[WTPIndex].subState = CW_WAITING_REQUEST;\n        CWACsend_command_to_hostapd_SEND_WLAN(WTPIndex);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseChangeStateEventRequestMessage(unsigned char *msg,\n\t\t\t\t\t     int len,\n\t\t\t\t\t     int *seqNumPtr, CWProtocolChangeStateEventRequestValues * valuesPtr)\n{\n\n\tCWProtocolMessage completeMsg;\n\tCWControlHeaderValues controlVal;\n\tint i;\n\tint offsetTillMessages;\n\n\tif (msg == NULL || seqNumPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Parsing Change State Event Request...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\t/* will be handled by the caller */\n\t\treturn CW_FALSE;\n\n\t/* different type */\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_REQUEST)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Change State Event Request\");\n\n\t*seqNumPtr = controlVal.seqNum;\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\toffsetTillMessages = completeMsg.offset;\n\tvaluesPtr->radioOperationalInfo.radiosCount = 0;\n\n\t/* parse message elements */\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\t\tunsigned short int elemType = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int elemLen = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\t/*CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen); */\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE:\n\t\t\t/* just count how many radios we have,\n\t\t\t * so we can allocate the array\n\t\t\t */\n\t\t\tvaluesPtr->radioOperationalInfo.radiosCount++;\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\tif (!(CWParseResultCode(&completeMsg, elemLen, &(valuesPtr->resultCode))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCW_CREATE_ARRAY_ERR(valuesPtr->radioOperationalInfo.radios,\n\t\t\t    valuesPtr->radioOperationalInfo.radiosCount,\n\t\t\t    CWRadioOperationalInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tcompleteMsg.offset = offsetTillMessages;\n\ti = 0;\n\n\twhile (completeMsg.offset - offsetTillMessages < controlVal.msgElemsLen) {\n\t\tunsigned short int type = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int len = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE:\n\t\t\tif (!\n\t\t\t    (CWParseWTPRadioOperationalState\n\t\t\t     (&completeMsg, len, &(valuesPtr->radioOperationalInfo.radios[i]))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\ti++;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\t}\n\t}\n\tCWDebugLog(\"Change State Event Request Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleChangeStateEventResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 0;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Assembling Change State Event Response...\");\n\t/*CW_CREATE_ARRAY_ERR(msgElems,\n\t *            msgElemCount,\n\t *            CWProtocolMessage,\n\t *            return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\t */\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWDebugLog(\"Change State Event Response Assembled\");\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACDiscoveryState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\n\n__inline__ int CWACGetHWVersion();\n__inline__ int CWACGetSWVersion();\n__inline__ int CWACGetStations();\n__inline__ int CWACGetLimit();\n__inline__ int CWACGetActiveWTPs();\n__inline__ int CWACGetMaxWTPs();\n__inline__ int CWACGetSecurity();\n__inline__ char *CWACGetName();\n__inline__ int CWACGetInterfacesCount();\n\n/*_________________________________________________________*/\n/*  *******************___FUNCTIONS___*******************  */\n\n/* send Discovery Response to the host at the specified address */\nCWBool CWAssembleDiscoveryResponse(CWProtocolMessage ** messagesPtr, int seqNum)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 4;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\tint fragmentsNum;\n\n\tint k = -1;\n\tif (messagesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (CWACSupportIPv6()) {\n\t\tmsgElemCount++;\n\t}\n\n\tCWLog(\"Send Discovery Response\");\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/* Assemble Message Elements */\n\tif ((!(CWAssembleMsgElemACDescriptor(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemACName(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemCWControlIPv4Addresses(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemACWTPRadioInformation(&(msgElems[++k]))))\n\t    /*(CWACSupportIPv6() && (!(CWAssembleMsgElemCWControlIPv6Addresses(&(msgElems[++k]))))) */\n\t    ) {\n\t\tCWErrorHandleLast();\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t}\n\n\treturn CWAssembleMessage(messagesPtr,\n\t\t\t\t &fragmentsNum,\n\t\t\t\t 0,\n\t\t\t\t seqNum,\n\t\t\t\t CW_MSG_TYPE_VALUE_DISCOVERY_RESPONSE,\n\t\t\t\t msgElems, msgElemCount, msgElemsBinding, msgElemBindingCount);\n}\n\nCWBool CWParseDiscoveryRequestMessage(unsigned char *msg, int len, int *seqNumPtr, CWDiscoveryRequestValues * valuesPtr)\n{\n\n\tCWControlHeaderValues controlVal;\n\tCWProtocolTransportHeaderValues transportVal;\n\tunsigned char RadioInfoABGN;\n\tint offsetTillMessages;\n\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL || seqNumPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Parse Discovery Request\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tCWBool dataFlag = CW_FALSE;\n\tif (!(CWParseTransportHeader(&completeMsg, &transportVal, &dataFlag, NULL)))\n\t\t/* will be handled by the caller */\n\t\treturn CW_FALSE;\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\t/* will be handled by the caller */\n\t\treturn CW_FALSE;\n\n\t/* different type */\n\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_DISCOVERY_REQUEST)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Discovery Request as Expected\");\n\n\t*seqNumPtr = controlVal.seqNum;\n\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\toffsetTillMessages = completeMsg.offset;\n\n\t/* (*valuesPtr).radios.radiosCount = 0; */\n\n\t/* parse message elements */\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\n\t\tunsigned short int elemType = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int elemLen = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\t/* CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen); */\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_DISCOVERY_TYPE_CW_TYPE:\n\t\t\tif (!(CWParseDiscoveryType(&completeMsg, elemLen, valuesPtr)))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_BOARD_DATA_CW_TYPE:\n\t\t\tif (!(CWParseWTPBoardData(&completeMsg, elemLen, &(valuesPtr->WTPBoardData))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_DESCRIPTOR_CW_TYPE:\n\t\t\tif (!(CWParseWTPDescriptor(&completeMsg, elemLen, &(valuesPtr->WTPDescriptor))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_FRAME_TUNNEL_MODE_CW_TYPE:\n\t\t\tif (!(CWParseWTPFrameTunnelMode(&completeMsg, elemLen, &(valuesPtr->frameTunnelMode))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_MAC_TYPE_CW_TYPE:\n\t\t\tif (!(CWParseWTPMACType(&completeMsg, elemLen, &(valuesPtr->MACType))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE:\n\t\t\tif (!(CWParseWTPRadioInformation(&completeMsg, elemLen, &RadioInfoABGN)))\n\t\t\t\treturn CW_FALSE;\n\n\t\t\tbreak;\n\t\t\t/*case CW_MSG_ELEMENT_WTP_RADIO_INFO_CW_TYPE:\n\t\t\t   // just count how many radios we have, so we can allocate the array\n\t\t\t   (*valuesPtr).radios.radiosCount++;\n\t\t\t   completeMsg.offset += elemLen;\n\t\t\t   break;\n\t\t\t */\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\n\t\t/*CWDebugLog(\"bytes: %d/%d\", (completeMsg.offset-offsetTillMessages), controlVal.msgElemsLen); */\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\t/*\n\t   // actually read each radio info\n\t   CW_CREATE_ARRAY_ERR((*valuesPtr).radios.radios, (*valuesPtr).radios.radiosCount, CWRadioInformationValues,\n\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\t   i = 0;\n\n\t   completeMsg.offset = offsetTillMessages;\n\t   while(i < (*valuesPtr).radios.radiosCount && (completeMsg.offset-offsetTillMessages) < controlVal.msgElemsLen) {\n\t   unsigned short int type=0;// = CWProtocolRetrieve32(&completeMsg);\n\t   unsigned short int len=0;// = CWProtocolRetrieve16(&completeMsg);\n\n\t   CWParseFormatMsgElem(&completeMsg,&type,&len);\n\n\t   switch(type) {\n\t   case CW_MSG_ELEMENT_WTP_RADIO_INFO_CW_TYPE:\n\t   if(!(CWParseWTPRadioInfo(&completeMsg, len, &(valuesPtr->radios), i))) return CW_FALSE; // will be handled by the caller\n\t   i++;\n\t   break;\n\t   default:\n\t   completeMsg.offset += len;\n\t   break;\n\t   }\n\t   }\n\t */\n\treturn CW_TRUE;\n}\n\nvoid CWDestroyDiscoveryRequestValues(CWDiscoveryRequestValues * valPtr)\n{\n\n\tint i;\n\n\tif (valPtr == NULL)\n\t\treturn;\n\tfor (i = 0; i < (valPtr->WTPDescriptor.vendorInfos).vendorInfosCount; i++) {\n\n\t\tCW_FREE_OBJECT(((valPtr->WTPDescriptor.vendorInfos).vendorInfos)[i].valuePtr);\n\t}\n\tCW_FREE_OBJECT((valPtr->WTPDescriptor.vendorInfos).vendorInfos);\n\n\t/*\n\t * BUG ML11\n\t *\n\t * 10/10/2009 - Donato Capitella\n\t */\n\tfor (i = 0; i < valPtr->WTPBoardData.vendorInfosCount; i++) {\n\t\tCW_FREE_OBJECT(valPtr->WTPBoardData.vendorInfos[i].valuePtr);\n\t}\n\tCW_FREE_OBJECT(valPtr->WTPBoardData.vendorInfos);\n\n\t/*CW_FREE_OBJECT((valPtr->radios).radios); */\n}\n"
  },
  {
    "path": "ACInterface.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap\n *\n *   Authors : Antonio Davoli (antonio.davoli@gmail.com)\n *   Donato Capitella (d.capitella@gmail.com)\n ************************************************************************************************/\n\n#include \"CWAC.h\"\n#include \"ACAppsProtocol.h\"\n#include \"CWVendorPayloads.h\"\n#include \"WUM.h\"\n\n#define LIST_CMD \"LIST\"\n#define SCAN_CMD \"SCAN\"\n#define QUIT_CMD \"QUIT\"\n\n#define LISTEN_PORT 1235\n#define COMMAND_BUFFER_SIZE 5120\n#define WTP_LIST_BUFFER_SIZE 1024\n\n#define CMD_TYPE_SIZE   sizeof(unsigned char)\n\nint is_valid_wtp_index(int index);\nint Readn(int sock, void *buf, size_t n);\n\n/********************************************************************\n * Now the only parameter need by the application thread manager    *\n * is the index of socket.                                          *\n ********************************************************************/\n\ntypedef struct {\n\tint index;\n} CWInterfaceThreadArg;\n\n/************************************************************************\n * CWOFDMSetValues provide to set the command values (type, parameters, *\n * output socket) on the correct wtp structure.                         *\n ************************************************************************/\n\nint CWOFDMSetValues(int selection, int socketIndex, OFDMControlValues * ofdmValues)\n{\n\n\tCWThreadMutexLock(&(gWTPs[selection].interfaceMutex));\n\n\tgWTPs[selection].ofdmValues = ofdmValues;\n\tgWTPs[selection].interfaceCommand = OFDM_CONTROL_CMD;\n\tgWTPs[selection].applicationIndex = socketIndex;\n\tCWSignalThreadCondition(&gWTPs[selection].interfaceWait);\n\tCWWaitThreadCondition(&gWTPs[selection].interfaceComplete, &gWTPs[selection].interfaceMutex);\n\n\tCWThreadMutexUnlock(&(gWTPs[selection].interfaceMutex));\n\n\treturn 0;\n}\n\nint CWVendorSetValues(int selection, int socketIndex, CWProtocolVendorSpecificValues * vendorValues)\n{\n\n\tCWThreadMutexLock(&(gWTPs[selection].interfaceMutex));\n\n\tgWTPs[selection].vendorValues = vendorValues;\n\tgWTPs[selection].interfaceCommand = UCI_CONTROL_CMD;\n\tgWTPs[selection].applicationIndex = socketIndex;\n\tCWSignalThreadCondition(&gWTPs[selection].interfaceWait);\n\tCWWaitThreadCondition(&gWTPs[selection].interfaceComplete, &gWTPs[selection].interfaceMutex);\n\n\tCWThreadMutexUnlock(&(gWTPs[selection].interfaceMutex));\n\n\treturn 0;\n}\n\nint CWWumSetValues(int selection, int socketIndex, CWProtocolVendorSpecificValues * vendorValues)\n{\n\n\tCWThreadMutexLock(&(gWTPs[selection].interfaceMutex));\n\n\tgWTPs[selection].vendorValues = vendorValues;\n\tgWTPs[selection].interfaceCommand = WTP_UPDATE_CMD;\n\tgWTPs[selection].applicationIndex = socketIndex;\n\tCWSignalThreadCondition(&gWTPs[selection].interfaceWait);\n\tCWWaitThreadCondition(&gWTPs[selection].interfaceComplete, &gWTPs[selection].interfaceMutex);\n\n\tCWThreadMutexUnlock(&(gWTPs[selection].interfaceMutex));\n\n\treturn 0;\n}\n\n/************************************************************************\n * CWManageApplication is the function that provide the management of   *\n * interaction with a single application.                               *\n * -------------------------------------------------------------------- *\n * The messages used are defined in ACAppsProtocol.h                    *\n ************************************************************************/\n\nCW_THREAD_RETURN_TYPE CWManageApplication(void *arg)\n{\n\n\tint socketIndex = ((CWInterfaceThreadArg *) arg)->index;\n\tCWSocket sock = appsManager.appSocket[socketIndex];\n\tint n, connected = htonl(CONNECTION_OK), gActiveWTPsTemp;\n\n\tchar commandBuffer[COMMAND_BUFFER_SIZE];\n\tchar wtpListBuffer[WTP_LIST_BUFFER_SIZE];\n\n\tint payload_size;\n\tint i, nameLength, numActiveWTPs = 0, wtpIndex;\n\tint iTosend, nLtoSend;\n\tunsigned char cmd_msg, msg_elem;\n\tOFDMControlValues *ofdmValues;\n\tCWProtocolVendorSpecificValues *vendorValues;\n\tCWVendorUciValues *uciValues;\n\tCWVendorWumValues *wumValues;\n\n\t/********************************************************************************\n\t * Write on application socket that connection setting is happened correctly.   *\n\t ********************************************************************************/\n\n\tif (Writen(sock, &connected, sizeof(int)) < 0) {\n\t\tCWLog(\"Error on writing on application socket \");\n\t\treturn NULL;\n\t}\n\n\t/*\n\t * Before starting, make sure to detach the thread because the parent\n\t * doesn't do a join and we risk resource leaks.\n\t *\n\t * ref -> BUG-TRL01\n\t * 15/10/2009 - Donato Capitella\n\t */\n\n\tpthread_detach(pthread_self());\t// no need here to check return value\n\n\t/************************\n\t *   Thread Main Loop   *\n\t ************************/\n\n\tCW_REPEAT_FOREVER {\n\n\t\tmemset(commandBuffer, 0, COMMAND_BUFFER_SIZE);\n\n\t\t/****************************************\n\t\t *      Waiting for client commands     *\n\t\t ****************************************/\n\n\t\tif ((n = Readn(sock, &cmd_msg, CMD_TYPE_SIZE)) > 0) {\n\n\t\t\tif (cmd_msg == QUIT_MSG) {\n\t\t\t\t/****************************************************\n\t\t\t\t *      Quit Message: Clean socket information      *\n\t\t\t\t ****************************************************/\n\t\t\t\tgoto quit_manage;\n\t\t\t}\n\n\t\t\tif (cmd_msg == LIST_MSG) {\n\n\t\t\t\t/****************************************\n\t\t\t\t *          Manage LIST command         *\n\t\t\t\t * ------------------------------------ *\n\t\t\t\t * 1. Get Number of active WTPs,        *\n\t\t\t\t * 2. Create Message Answer,            *\n\t\t\t\t * 3. Send To client socket.            *\n\t\t\t\t ****************************************/\n\n\t\t\t\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex))) {\n\t\t\t\t\tCWLog(\"Error locking the mutex\");\n\t\t\t\t\treturn NULL;\n\t\t\t\t}\n\n\t\t\t\tgActiveWTPsTemp = gActiveWTPs;\n\n\t\t\t\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\t\t\t\tif (gActiveWTPsTemp > 0)\n\t\t\t\t\tfor (i = 0; i < gMaxWTPs; i++)\n\t\t\t\t\t\tif (gWTPs[i].isNotFree)\n\t\t\t\t\t\t\tif (!gWTPs[i].WTPProtocolManager.name)\n\t\t\t\t\t\t\t\tgActiveWTPsTemp -= 1;\n\n\t\t\t\tnumActiveWTPs = htonl(gActiveWTPsTemp);\n\n\t\t\t\tmemset(wtpListBuffer, 0, sizeof(wtpListBuffer));\n\t\t\t\tpayload_size = 0;\n\n\t\t\t\tmemcpy(wtpListBuffer, &numActiveWTPs, sizeof(int));\n\t\t\t\tpayload_size = sizeof(int);\n\n\t\t\t\tif (gActiveWTPsTemp > 0) {\n\t\t\t\t\tfor (i = 0; i < gMaxWTPs; i++) {\n\n\t\t\t\t\t\tif (gWTPs[i].isNotFree) {\n\n\t\t\t\t\t\t\tif (!gWTPs[i].WTPProtocolManager.name)\n\t\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\tnameLength = strlen(gWTPs[i].WTPProtocolManager.name);\n\n\t\t\t\t\t\t\tiTosend = htonl(i);\n\t\t\t\t\t\t\tnLtoSend = htonl(nameLength);\n\n\t\t\t\t\t\t\tmemcpy(wtpListBuffer + payload_size, &iTosend, sizeof(int));\n\t\t\t\t\t\t\tpayload_size += sizeof(int);\n\n\t\t\t\t\t\t\tmemcpy(wtpListBuffer + payload_size, &nLtoSend, sizeof(int));\n\t\t\t\t\t\t\tpayload_size += sizeof(int);\n\n\t\t\t\t\t\t\tmemcpy(wtpListBuffer + payload_size,\n\t\t\t\t\t\t\t       gWTPs[i].WTPProtocolManager.name,\n\t\t\t\t\t\t\t       strlen(gWTPs[i].WTPProtocolManager.name));\n\t\t\t\t\t\t\tpayload_size += strlen(gWTPs[i].WTPProtocolManager.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (Writen(sock, wtpListBuffer, payload_size) < 0)\n\t\t\t\t\tCWLog(\"Error on write message on application socket\");\n\n\t\t\t}\n\n\t\t\tif (cmd_msg == CONF_UPDATE_MSG) {\n\n\t\t\t\t/****************************************\n\t\t\t\t * Manage CONF command          *\n\t\t\t\t * ------------------------------------ *\n\t\t\t\t * 1. Select the type of CONF_UPDATE,   *\n\t\t\t\t * 2. Get Index of WTP,         *\n\t\t\t\t * 3. Manage request.           *\n\t\t\t\t ****************************************/\n\n\t\t\t\tif ((n = Readn(sock, commandBuffer, sizeof(msg_elem) + sizeof(wtpIndex))) < 0) {\n\t\t\t\t\tCWLog(\"Error while reading from socket.\");\n\t\t\t\t\tgoto quit_manage;\n\t\t\t\t}\n\n\t\t\t\tmemcpy(&msg_elem, commandBuffer, sizeof(unsigned char));\t/* CONF_UPDATE type */\n\t\t\t\tmemcpy(&wtpIndex, commandBuffer + sizeof(unsigned char), sizeof(int));\t/* WTP Index */\n\n\t\t\t\twtpIndex = ntohl(wtpIndex);\n\n\t\t\t\t/* Check if WTP Index is valid */\n\t\t\t\tif (!is_valid_wtp_index(wtpIndex)) {\n\t\t\t\t\tCWLog(\"WTP Index non valid!\");\n\t\t\t\t\tgoto quit_manage;\n\t\t\t\t}\n\n\t\t\t\tswitch (msg_elem) {\n\t\t\t\tcase MSG_ELEMENT_TYPE_OFDM:{\n\t\t\t\t\t\t/* Antonio Case */\n\t\t\t\t\t\tCW_CREATE_OBJECT_ERR(ofdmValues, OFDMControlValues, {\n\t\t\t\t\t\t\t\t     CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t\t\t     return 0;\n\t\t\t\t\t\t\t\t     }\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif ((n = Readn(sock, ofdmValues, sizeof(OFDMControlValues))) < 0) {\n\t\t\t\t\t\t\tCWLog(\"Error while reading from socket\");\n\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t/****************************************************\n\t\t\t\t\t * Two behaviors availables:                        *\n\t\t\t\t\t *    - One message element For All WTPs Active     *\n\t\t\t\t\t *    - One message for a specific WTP              *\n\t\t\t\t\t ****************************************************/\n\n\t\t\t\t\t\tif (wtpIndex == ALL_ACTIVE_WTPS) {\t/* All wpts case */\n\n\t\t\t\t\t\t\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex))) {\n\t\t\t\t\t\t\t\tCWLog(\"Error locking the mutex\");\n\t\t\t\t\t\t\t\treturn NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnumActiveWTPs = gActiveWTPs;\n\t\t\t\t\t\t\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\t\t\t\t\t\t\tif (numActiveWTPs > 0) {\n\t\t\t\t\t\t\t\tfor (i = 0; i < gMaxWTPs; i++) {\n\t\t\t\t\t\t\t\t\tif (gWTPs[i].isNotFree) {\n\t\t\t\t\t\t\t\t\t\tCWOFDMSetValues(i, socketIndex,\n\t\t\t\t\t\t\t\t\t\t\t\tofdmValues);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else\t/* One specific Wtp Case */\n\t\t\t\t\t\t\tCWOFDMSetValues(wtpIndex, socketIndex, ofdmValues);\n\n\t\t\t\t\t\tCW_FREE_OBJECT(ofdmValues);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase MSG_ELEMENT_TYPE_VENDOR_UCI:{\n\t\t\t\t\t\t/* Matteo Case */\n\t\t\t\t\t\t/*Do stuff to parse uci payload */\n\t\t\t\t\t\tint commandLength = 0;\n\t\t\t\t\t\tCW_CREATE_OBJECT_ERR(vendorValues, CWProtocolVendorSpecificValues, {\n\t\t\t\t\t\t\t\t     CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t\t\t     return 0;\n\t\t\t\t\t\t\t\t     }\n\t\t\t\t\t\t);\n\t\t\t\t\t\tCW_CREATE_OBJECT_ERR(uciValues, CWVendorUciValues, {\n\t\t\t\t\t\t\t\t     CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t\t\t     return 0;\n\t\t\t\t\t\t\t\t     }\n\t\t\t\t\t\t);\n\t\t\t\t\t\tvendorValues->vendorPayloadType =\n\t\t\t\t\t\t    CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI;\n\t\t\t\t\t\tuciValues->response = NULL;\n\n\t\t\t\t\t\tif ((n =\n\t\t\t\t\t\t     Readn(sock, commandBuffer,\n\t\t\t\t\t\t\t   sizeof(unsigned char) + sizeof(int))) < 0) {\n\t\t\t\t\t\t\tCWLog(\"Error while reading from socket.\");\n\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmemcpy(&(uciValues->command), commandBuffer, sizeof(unsigned char));\n\t\t\t\t\t\tmemcpy(&commandLength, commandBuffer + sizeof(unsigned char),\n\t\t\t\t\t\t       sizeof(int));\n\t\t\t\t\t\tcommandLength = ntohl(commandLength);\n\n\t\t\t\t\t\tif (commandLength > 0) {\n\t\t\t\t\t\t\tif ((n =\n\t\t\t\t\t\t\t     Readn(sock, commandBuffer + sizeof(char) + sizeof(int),\n\t\t\t\t\t\t\t\t   commandLength)) < 0) {\n\t\t\t\t\t\t\t\tCWLog(\"Error while reading from socket.\");\n\t\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tCW_CREATE_STRING_ERR(uciValues->commandArgs, commandLength, {\n\t\t\t\t\t\t\t\t\t     CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t\t\t\t     return 0;\n\t\t\t\t\t\t\t\t\t     }\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tmemcpy(uciValues->commandArgs,\n\t\t\t\t\t\t\t       commandBuffer + sizeof(unsigned char) + sizeof(int),\n\t\t\t\t\t\t\t       sizeof(char) * commandLength);\n\t\t\t\t\t\t\tuciValues->commandArgs[commandLength] = '\\0';\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tuciValues->commandArgs = NULL;\n\n\t\t\t\t\t\tvendorValues->payload = uciValues;\n\n\t\t\t\t\t/****************************************************\n\t\t\t\t\t * Two behaviors availables:                        *\n\t\t\t\t\t *      - One message element For All WTPs Active   *\n\t\t\t\t\t *      - One message for a specific WTP            *\n\t\t\t\t\t ****************************************************/\n\n\t\t\t\t\t\tif (wtpIndex == ALL_ACTIVE_WTPS) {\t/* All wpts case */\n\n\t\t\t\t\t\t\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex))) {\n\t\t\t\t\t\t\t\tCWLog(\"Error locking the mutex\");\n\t\t\t\t\t\t\t\treturn NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnumActiveWTPs = gActiveWTPs;\n\t\t\t\t\t\t\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\t\t\t\t\t\t\tif (numActiveWTPs > 0) {\n\t\t\t\t\t\t\t\tfor (i = 0; i < gMaxWTPs; i++) {\n\t\t\t\t\t\t\t\t\tif (gWTPs[i].isNotFree) {\n\t\t\t\t\t\t\t\t\t\tprintf\n\t\t\t\t\t\t\t\t\t\t    (\"Sending UCI Configuration Message to: %d - %s \\n\",\n\t\t\t\t\t\t\t\t\t\t     i,\n\t\t\t\t\t\t\t\t\t\t     gWTPs[i].WTPProtocolManager.name);\n\t\t\t\t\t\t\t\t\t\tCWVendorSetValues(i, socketIndex,\n\t\t\t\t\t\t\t\t\t\t\t\t  vendorValues);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else\t/* One specific Wtp Case */\n\t\t\t\t\t\t\tCWVendorSetValues(wtpIndex, socketIndex, vendorValues);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase MSG_ELEMENT_TYPE_VENDOR_WUM:{\n\t\t\t\t\t\t/* Donato's Case */\n\n\t\t\t\t\t\tCW_CREATE_OBJECT_ERR(vendorValues, CWProtocolVendorSpecificValues, {\n\t\t\t\t\t\t\t\t     CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t\t\t     return 0;\n\t\t\t\t\t\t\t\t     }\n\t\t\t\t\t\t);\n\t\t\t\t\t\tCW_CREATE_OBJECT_ERR(wumValues, CWVendorWumValues, {\n\t\t\t\t\t\t\t\t     CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t\t\t     return 0;\n\t\t\t\t\t\t\t\t     }\n\t\t\t\t\t\t);\n\t\t\t\t\t\tvendorValues->vendorPayloadType =\n\t\t\t\t\t\t    CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM;\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t * Read WTP Update Message fields into the wumValues structure\n\t\t\t\t\t\t */\n\n\t\t\t\t\t\tif ((n = Readn(sock, &(wumValues->type), sizeof(unsigned char))) < 0) {\n\t\t\t\t\t\t\tCWLog(\"Error while reading from socket.\");\n\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (wumValues->type == WTP_UPDATE_REQUEST) {\n\t\t\t\t\t\t\tif ((n =\n\t\t\t\t\t\t\t     Readn(sock, commandBuffer,\n\t\t\t\t\t\t\t\t   3 * sizeof(unsigned char) + sizeof(int))) < 0) {\n\t\t\t\t\t\t\t\tCWLog(\"Error while reading from socket.\");\n\t\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tmemcpy(&(wumValues->_major_v_), commandBuffer,\n\t\t\t\t\t\t\t       sizeof(unsigned char));\n\t\t\t\t\t\t\tmemcpy(&(wumValues->_minor_v_),\n\t\t\t\t\t\t\t       commandBuffer + sizeof(unsigned char),\n\t\t\t\t\t\t\t       sizeof(unsigned char));\n\t\t\t\t\t\t\tmemcpy(&(wumValues->_revision_v_),\n\t\t\t\t\t\t\t       commandBuffer + 2 * sizeof(unsigned char),\n\t\t\t\t\t\t\t       sizeof(unsigned char));\n\t\t\t\t\t\t\tmemcpy(&(wumValues->_pack_size_),\n\t\t\t\t\t\t\t       commandBuffer + 3 * sizeof(unsigned char),\n\t\t\t\t\t\t\t       sizeof(unsigned int));\n\t\t\t\t\t\t\twumValues->_pack_size_ = ntohl(wumValues->_pack_size_);\n\t\t\t\t\t\t} else if (wumValues->type == WTP_CUP_FRAGMENT) {\n\t\t\t\t\t\t\tint seqNum;\n\t\t\t\t\t\t\tint fragSize;\n\n\t\t\t\t\t\t\t/* Read sequence number and fragment size */\n\t\t\t\t\t\t\tif ((n = Readn(sock, commandBuffer, 2 * sizeof(int))) < 0) {\n\t\t\t\t\t\t\t\tCWLog(\"Error while reading from socket.\");\n\t\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tmemcpy(&seqNum, commandBuffer, sizeof(int));\n\t\t\t\t\t\t\tmemcpy(&fragSize, commandBuffer + sizeof(int), sizeof(int));\n\n\t\t\t\t\t\t\tseqNum = ntohl(seqNum);\n\t\t\t\t\t\t\tfragSize = ntohl(fragSize);\n\n\t\t\t\t\t\t\tif (seqNum < 0) {\n\t\t\t\t\t\t\t\tCWLog(\"Update with sequence number < 0 not valid.\");\n\t\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (fragSize <= 0) {\n\t\t\t\t\t\t\t\tCWLog(\"Update with fragment size <= 0 not valid.\");\n\t\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/* Read update package into buffer */\n\t\t\t\t\t\t\tunsigned char *buf = malloc(fragSize);\n\t\t\t\t\t\t\tif (buf == NULL) {\n\t\t\t\t\t\t\t\tCWLog(\"Can't allocate memory\");\n\t\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ((n = Readn(sock, buf, fragSize)) < 0) {\n\t\t\t\t\t\t\t\tCWLog(\"Error while reading from socket.\");\n\t\t\t\t\t\t\t\tgoto quit_manage;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\twumValues->_cup_ = buf;\n\t\t\t\t\t\t\twumValues->_seq_num_ = seqNum;\n\t\t\t\t\t\t\twumValues->_cup_fragment_size_ = fragSize;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvendorValues->payload = wumValues;\n\n\t\t\t\t\t\t/* Send Request */\n\t\t\t\t\t\tif (wtpIndex == ALL_ACTIVE_WTPS) {\t/* All wpts case */\n\n\t\t\t\t\t\t\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex))) {\n\t\t\t\t\t\t\t\tCWLog(\"Error locking the mutex\");\n\t\t\t\t\t\t\t\treturn NULL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnumActiveWTPs = gActiveWTPs;\n\t\t\t\t\t\t\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\t\t\t\t\t\t\tif (numActiveWTPs > 0) {\n\t\t\t\t\t\t\t\tfor (i = 0; i < gMaxWTPs; i++) {\n\t\t\t\t\t\t\t\t\tif (gWTPs[i].isNotFree) {\n\t\t\t\t\t\t\t\t\t\tprintf\n\t\t\t\t\t\t\t\t\t\t    (\"Sending WUM Configuration Message to: %d - %s \\n\",\n\t\t\t\t\t\t\t\t\t\t     i,\n\t\t\t\t\t\t\t\t\t\t     gWTPs[i].WTPProtocolManager.name);\n\t\t\t\t\t\t\t\t\t\tCWWumSetValues(i, socketIndex,\n\t\t\t\t\t\t\t\t\t\t\t       vendorValues);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else\t/* One specific Wtp Case */\n\t\t\t\t\t\t\tCWWumSetValues(wtpIndex, socketIndex, vendorValues);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\t/* Error Case: Not correct msg_elem type */\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tCWLog(\"Error on receive application command (read socket)\");\n\t\t\tgoto quit_manage;\n\t\t}\n\t}\n\n quit_manage:\n\n\tif (!CWErr(CWThreadMutexLock(&appsManager.numSocketFreeMutex))) {\n\t\tCWLog(\"Error locking numSocketFree Mutex\");\n\t\treturn NULL;\n\t}\n\n\tappsManager.isFree[socketIndex] = CW_TRUE;\n\tappsManager.numSocketFree++;\n\n\tCWDestroyThreadMutex(&appsManager.socketMutex[socketIndex]);\n\n\tCWThreadMutexUnlock(&appsManager.numSocketFreeMutex);\n\n\tclose(sock);\n\treturn NULL;\n}\n\n/****************************************************************************\n * CWInterface is the function that provide the interaction between AC and  *\n * extern applications. Listen on main Inet familty socket and create a     *\n * CWManageApplication thread for every client connected.                   *\n ****************************************************************************/\n\nCW_THREAD_RETURN_TYPE CWInterface(void *arg)\n{\n\n\tCWSocket listen_sock, conn_sock;\n\tstruct sockaddr_in servaddr;\n\tCWInterfaceThreadArg *argPtr;\n\tCWThread thread_id;\n\tint i, clientFull = htonl(FULL_CLIENT_CONNECTED), optValue = 1;\n\n\t/****************************************************\n\t * Setup of Application Socket Management Structure *\n\t ****************************************************/\n\n\tfor (i = 0; i < MAX_APPS_CONNECTED_TO_AC; i++)\n\t\tappsManager.isFree[i] = CW_TRUE;\n\n\tappsManager.numSocketFree = MAX_APPS_CONNECTED_TO_AC;\n\n\tif (!CWErr(CWCreateThreadMutex(&appsManager.numSocketFreeMutex))) {\n\t\tCWLog(\"Error on mutex creation on appManager structure\");\n\t\treturn NULL;\n\t}\n\n\t/****************************************************\n\t * Setup (Creation and filling) of main socket      *\n\t ****************************************************/\n\n\tif ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {\n\t\tCWLog(\"Error on socket creation on Interface\");\n\t\treturn NULL;\n\t}\n\n\tmemset(&servaddr, 0, sizeof(servaddr));\n\n\tservaddr.sin_family = AF_INET;\n\tservaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\t/* Not Extern: INADDR_ANY */\n\tservaddr.sin_port = htons(LISTEN_PORT);\n\n\tif (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &optValue, sizeof(int)) == -1) {\n\t\tCWLog(\"Error on socket creation on Interface\");\n\t\treturn NULL;\n\t}\n\n\t/************************************\n\t * Binding socket and Listen call   *\n\t ************************************/\n\n\tif (bind(listen_sock, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)) < 0) {\n\t\tCWLog(\"Error on Binding\");\n\t\treturn NULL;\n\t}\n\n\tif (listen(listen_sock, MAX_APPS_CONNECTED_TO_AC) < 0) {\n\t\tCWLog(\"Error on LIsTsocket creation\");\n\t\treturn NULL;\n\t}\n\n\t/********************************\n\t *          Main Loop           *\n\t ********************************/\n\n\tCW_REPEAT_FOREVER {\n\t\tif ((conn_sock = accept(listen_sock, (struct sockaddr *)NULL, NULL)) > 0) {\n\n\t\t\t/************************************************************************\n\t\t\t * Check (with lock) the number of socket free at the moment of accept, *\n\t\t\t * if this value is greater than 0 will be spawn a new Manage thread.   *\n\t\t\t ************************************************************************/\n\n\t\t\tif (!CWErr(CWThreadMutexLock(&appsManager.numSocketFreeMutex))) {\n\t\t\t\tCWLog(\"Error locking numSocketFree Mutex\");\n\t\t\t\treturn NULL;\n\t\t\t}\n\n\t\t\tif (appsManager.numSocketFree > 0) {\n\n\t\t\t\tCW_CREATE_OBJECT_ERR(argPtr, CWInterfaceThreadArg, {\n\t\t\t\t\t\t     CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t     return 0;\n\t\t\t\t\t\t     }\n\t\t\t\t);\n\n\t\t\t\t/************************************\n\t\t\t\t *  Search socket for application   *\n\t\t\t\t ************************************/\n\n\t\t\t\tfor (i = 0; i < MAX_APPS_CONNECTED_TO_AC; i++) {\n\t\t\t\t\tif (appsManager.isFree[i] == CW_TRUE) {\n\t\t\t\t\t\targPtr->index = i;\n\t\t\t\t\t\tappsManager.isFree[i] = CW_FALSE;\n\t\t\t\t\t\tappsManager.appSocket[i] = conn_sock;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tappsManager.numSocketFree--;\n\t\t\t\tCWThreadMutexUnlock(&appsManager.numSocketFreeMutex);\n\n\t\t\t\tif (!CWErr(CWCreateThreadMutex(&appsManager.socketMutex[argPtr->index]))) {\n\t\t\t\t\tCWLog(\"Error on mutex creation on appManager structure\");\n\t\t\t\t\treturn NULL;\n\t\t\t\t}\n\n\t\t\t\tif (!CWErr(CWCreateThread(&thread_id, CWManageApplication, argPtr))) {\n\t\t\t\t\tCWLog(\"Error on thread CWManageApplication creation\");\n\t\t\t\t\tappsManager.isFree[argPtr->index] = CW_TRUE;\n\t\t\t\t\tclose(conn_sock);\n\t\t\t\t\tCW_FREE_OBJECT(argPtr);\n\t\t\t\t\t/*\n\t\t\t\t\t * If we can't create the thread, we have to increment numSocketFree.\n\t\t\t\t\t *\n\t\t\t\t\t *   ref -> BUG-LE01\n\t\t\t\t\t *   15/10/2009 - Donato Capitella\n\t\t\t\t\t */\n\t\t\t\t\tif (!CWErr(CWThreadMutexLock(&appsManager.numSocketFreeMutex))) {\n\t\t\t\t\t\tCWLog(\"Error locking numSocketFree Mutex\");\n\t\t\t\t\t\treturn NULL;\n\t\t\t\t\t}\n\t\t\t\t\tappsManager.numSocketFree++;\n\t\t\t\t\tCWThreadMutexUnlock(&appsManager.numSocketFreeMutex);\n\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tCWThreadMutexUnlock(&appsManager.numSocketFreeMutex);\n\n\t\t\t\t/****************************************************************\n\t\t\t\t *  There isn't space for another client, send error answer.    *\n\t\t\t\t ***************************************************************/\n\n\t\t\t\tif (Writen(conn_sock, &clientFull, sizeof(int)) < 0) {\n\t\t\t\t\tprintf(\"Error on sending Error Message\\n\");\n\t\t\t\t\tclose(conn_sock);\n\t\t\t\t}\n\t\t\t}\n\t\t} else\n\t\t\tCWLog(\"Error on accept (applications) system call\");\n\t}\n\n\tCWDestroyThreadMutex(&appsManager.numSocketFreeMutex);\n\tclose(listen_sock);\n}\n\nint is_valid_wtp_index(int wtpIndex)\n{\n\tif (wtpIndex < gMaxWTPs && gWTPs[wtpIndex].isNotFree)\n\t\treturn CW_TRUE;\n\treturn CW_FALSE;\n}\n\n/*\n * Steven's readn().\n */\nint readn(int fd, void *vptr, size_t n)\n{\n\tsize_t nleft;\n\tssize_t nread;\n\tchar *ptr;\n\n\tptr = vptr;\n\tnleft = n;\n\twhile (nleft > 0) {\n\t\tif ((nread = recv(fd, ptr, nleft, 0)) < 0) {\n\t\t\tif (errno == EINTR)\n\t\t\t\tnread = 0;\t/* and call read() again */\n\t\t\telse\n\t\t\t\treturn (-1);\n\t\t} else if (nread == 0)\n\t\t\tbreak;\t/* EOF */\n\n\t\tnleft -= nread;\n\t\tptr += nread;\n\t}\n\treturn (n - nleft);\t/* return >= 0 */\n}\n\nint Readn(int fd, void *ptr, size_t nbytes)\n{\n\tint n;\n\n\tif ((n = readn(fd, ptr, nbytes)) < 0) {\n\t\tCWLog(\"Error while reading data from socket.\");\n\t\treturn -1;\n\t}\n\n\treturn n;\n}\n"
  },
  {
    "path": "ACInterface.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria          *\n *                         Informatica Universita' Campus BioMedico - Italy                *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *           Daniele De Sanctis (danieledesanctis@gmail.com)                               *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                     *\n *           Donato Capitella (d.capitella@gmail.com)                                      *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_ACInterface_HEADER__\n#define __CAPWAP_ACInterface_HEADER__\n\n//No Interface Command\n#define NO_CMD          0\n//Manual setting for QoS values\n#define QOS_CMD         1\n#define CLEAR_CONFIG_MSG_CMD    2\n/* 2009 Update: Manual setting for OFDM values*/\n#define OFDM_CONTROL_CMD        3\n/*Update 2009:\n        Manage UCI configuration command*/\n#define UCI_CONTROL_CMD 4\n/* Manage WTP Update Command */\n#define WTP_UPDATE_CMD  5\n\n#endif\n"
  },
  {
    "path": "ACJoinState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool CWAssembleJoinResponse(CWProtocolMessage ** messagesPtr,\n\t\t\t      int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList);\n\nCWBool CWParseJoinRequestMessage(unsigned char *msg, int len, int *seqNumPtr, CWProtocolJoinRequestValues * valuesPtr);\n\nCWBool CWSaveJoinRequestMessage(CWProtocolJoinRequestValues * joinRequest, CWWTPProtocolManager * WTPProtocolManager);\n\nCWBool ACEnterJoin(int WTPIndex, CWProtocolMessage * msgPtr)\n{\n\tint seqNum;\n\tCWProtocolJoinRequestValues joinRequest;\n\tCWList msgElemList = NULL;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"######### Join State #########\");\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!(CWParseJoinRequestMessage(msgPtr->msg, msgPtr->offset, &seqNum, &joinRequest))) {\n\t\t/* note: we can kill our thread in case of out-of-memory\n\t\t * error to free some space.\n\t\t * we can see this just calling CWErrorGetLastErrorCode()\n\t\t */\n\t\treturn CW_FALSE;\n\t}\n\t// cancel waitJoin timer\n\tif (!CWTimerCancel(&(gWTPs[WTPIndex].currentTimer))) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCWBool ACIpv4List = CW_FALSE;\n\tCWBool ACIpv6List = CW_FALSE;\n\tCWBool resultCode = CW_TRUE;\n\tint resultCodeValue = CW_PROTOCOL_SUCCESS;\n\t/* CWBool sessionID = CW_FALSE; */\n\n\tif (!(CWSaveJoinRequestMessage(&joinRequest, &(gWTPs[WTPIndex].WTPProtocolManager)))) {\n\n\t\tresultCodeValue = CW_PROTOCOL_FAILURE_RES_DEPLETION;\n\t}\n\n\tCWMsgElemData *auxData;\n\tif (ACIpv4List) {\n\t\tCW_CREATE_OBJECT_ERR(auxData, CWMsgElemData, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tauxData->type = CW_MSG_ELEMENT_AC_IPV4_LIST_CW_TYPE;\n\t\tauxData->value = 0;\n\t\tCWAddElementToList(&msgElemList, auxData);\n\t}\n\tif (ACIpv6List) {\n\t\tCW_CREATE_OBJECT_ERR(auxData, CWMsgElemData, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tauxData->type = CW_MSG_ELEMENT_AC_IPV6_LIST_CW_TYPE;\n\t\tauxData->value = 0;\n\t\tCWAddElementToList(&msgElemList, auxData);\n\t}\n\tif (resultCode) {\n\t\tCW_CREATE_OBJECT_ERR(auxData, CWMsgElemData, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tauxData->type = CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE;\n\t\tauxData->value = resultCodeValue;\n\t\tCWAddElementToList(&msgElemList, auxData);\n\t}\n\t/*\n\t   if(sessionID){\n\t   CW_CREATE_OBJECT_ERR(auxData, CWMsgElemData, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\t   auxData->type =  CW_MSG_ELEMENT_SESSION_ID_CW_TYPE;\n\t   auxData->value = CWRandomIntInRange(0, INT_MAX);\n\t   CWAddElementToList(&msgElemList,auxData);\n\t   }\n\t */\n\n\t/* random session ID */\n\tif (!(CWAssembleJoinResponse(&(gWTPs[WTPIndex].messages),\n\t\t\t\t     &(gWTPs[WTPIndex].messagesCount), gWTPs[WTPIndex].pathMTU, seqNum, msgElemList))) {\n\n\t\tCWDeleteList(&msgElemList, CWProtocolDestroyMsgElemData);\n\t\treturn CW_FALSE;\n\t}\n\n\tCWDeleteList(&msgElemList, CWProtocolDestroyMsgElemData);\n\n\tif (!CWACSendFragments(WTPIndex)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tgWTPs[WTPIndex].currentState = CW_ENTER_CONFIGURE;\n\n\treturn CW_TRUE;\n}\n\n/*\n * Assemble Join Response.\n */\nCWBool CWAssembleJoinResponse(CWProtocolMessage ** messagesPtr,\n\t\t\t      int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 0;\n\t/* Result code is not included because it's already\n\t * in msgElemList. Control IPv6 to be added.\n\t */\n\tconst int mandatoryMsgElemCount = 4;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\tint i;\n\tCWListElement *current;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL || msgElemList == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tmsgElemCount = CWCountElementInList(msgElemList);\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems,\n\t\t\t\t\t msgElemCount + mandatoryMsgElemCount,\n\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWDebugLog(\"Assembling Join Response...\");\n\n\tif ((!(CWAssembleMsgElemACDescriptor(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemACName(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemCWControlIPv4Addresses(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemACWTPRadioInformation(&(msgElems[++k]))))\n\t    ) {\n\t\tCWErrorHandleLast();\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\t/* error will be handled by the caller */\n\t\treturn CW_FALSE;\n\t}\n\n\tcurrent = msgElemList;\n\tfor (i = 0; i < msgElemCount; i++) {\n\n\t\tswitch (((CWMsgElemData *) (current->data))->type) {\n\n\t\tcase CW_MSG_ELEMENT_AC_IPV4_LIST_CW_TYPE:\n\t\t\tif (!(CWAssembleMsgElemACIPv4List(&(msgElems[++k]))))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_AC_IPV6_LIST_CW_TYPE:\n\t\t\tif (!(CWAssembleMsgElemACIPv6List(&(msgElems[++k]))))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\tif (!(CWAssembleMsgElemResultCode(&(msgElems[++k]), ((CWMsgElemData *) current->data)->value)))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\t\t/*\n\t\t\t   case CW_MSG_ELEMENT_SESSION_ID_CW_TYPE:\n\t\t\t   if (!(CWAssembleMsgElemSessionID(&(msgElems[++k]), ((CWMsgElemData *) current->data)->value)))\n\t\t\t   goto cw_assemble_error;\n\t\t\t   break;\n\t\t\t */\n\t\tdefault:{\n\t\t\t\tint j;\n\t\t\t\tfor (j = 0; j <= k; j++) {\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[j]);\n\t\t\t\t}\n\t\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t\t    \"Unrecognized Message Element for Join Response Message\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcurrent = current->next;\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_JOIN_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount + mandatoryMsgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWDebugLog(\"Join Response Assembled\");\n\n\treturn CW_TRUE;\n\n cw_assemble_error:{\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\t/* error will be handled by the caller */\n\t\treturn CW_FALSE;\n\t}\n\treturn CW_TRUE;\n}\n\n/*\n * Parses Join Request.\n */\nCWBool CWParseJoinRequestMessage(unsigned char *msg, int len, int *seqNumPtr, CWProtocolJoinRequestValues * valuesPtr)\n{\n\n\tCWControlHeaderValues controlVal;\n\tint offsetTillMessages;\n\tCWProtocolMessage completeMsg;\n\tunsigned char RadioInfoABGN;\n\n\tif (msg == NULL || seqNumPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Parse Join Request\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\t/* will be handled by the caller */\n\t\treturn CW_FALSE;\n\n\t/* different type */\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_JOIN_REQUEST)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Join Request as Expected\");\n\n\t*seqNumPtr = controlVal.seqNum;\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\toffsetTillMessages = completeMsg.offset;\n\n\t/* parse message elements */\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\n\t\tunsigned short int elemType = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int elemLen = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\t/* CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen); */\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_LOCATION_DATA_CW_TYPE:\n\t\t\tif (!(CWParseLocationData(&completeMsg, elemLen, &(valuesPtr->location))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_WTP_BOARD_DATA_CW_TYPE:\n\t\t\tif (!(CWParseWTPBoardData(&completeMsg, elemLen, &(valuesPtr->WTPBoardData))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_SESSION_ID_CW_TYPE:\n\t\t\tvaluesPtr->sessionID = CWParseSessionID(&completeMsg, elemLen);\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_WTP_DESCRIPTOR_CW_TYPE:\n\t\t\tif (!(CWParseWTPDescriptor(&completeMsg, elemLen, &(valuesPtr->WTPDescriptor))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_WTP_IPV4_ADDRESS_CW_TYPE:\n\t\t\tif (!(CWParseWTPIPv4Address(&completeMsg, elemLen, valuesPtr)))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_WTP_NAME_CW_TYPE:\n\t\t\tif (!(CWParseWTPName(&completeMsg, elemLen, &(valuesPtr->name))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_WTP_FRAME_TUNNEL_MODE_CW_TYPE:\n\t\t\tif (!(CWParseWTPFrameTunnelMode(&completeMsg, elemLen, &(valuesPtr->frameTunnelMode))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_WTP_MAC_TYPE_CW_TYPE:\n\t\t\tif (!(CWParseWTPMACType(&completeMsg, elemLen, &(valuesPtr->MACType))))\n\t\t\t\t/* will be handled by the caller */\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE:\n\t\t\tif (!(CWParseWTPRadioInformation(&completeMsg, elemLen, &RadioInfoABGN)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tCWLog(\"Unrecognized Message Element(%d) in Discovery response\", elemType);\n\t\t\tbreak;\n\t\t}\n\t\t/*CWDebugLog(\"bytes: %d/%d\", (completeMsg.offset-offsetTillMessages), controlVal.msgElemsLen); */\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveJoinRequestMessage(CWProtocolJoinRequestValues * joinRequest, CWWTPProtocolManager * WTPProtocolManager)\n{\n\n\tCWDebugLog(\"Saving Join Request...\");\n\n\tif (joinRequest == NULL || WTPProtocolManager == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((joinRequest->location) != NULL) {\n\n\t\tCW_FREE_OBJECT(WTPProtocolManager->locationData);\n\t\tWTPProtocolManager->locationData = joinRequest->location;\n\t} else\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((joinRequest->name) != NULL) {\n\n\t\tCW_FREE_OBJECT(WTPProtocolManager->name);\n\t\tWTPProtocolManager->name = joinRequest->name;\n\t} else\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_FREE_OBJECT((WTPProtocolManager->WTPBoardData).vendorInfos);\n\tWTPProtocolManager->WTPBoardData = joinRequest->WTPBoardData;\n\n\tWTPProtocolManager->sessionID = joinRequest->sessionID;\n\tWTPProtocolManager->ipv4Address = joinRequest->addr;\n\n\tWTPProtocolManager->descriptor = joinRequest->WTPDescriptor;\n\tWTPProtocolManager->radiosInfo.radioCount = (joinRequest->WTPDescriptor).radiosInUse;\n\tCW_FREE_OBJECT(WTPProtocolManager->radiosInfo.radiosInfo);\n\n\tCW_CREATE_ARRAY_ERR(WTPProtocolManager->radiosInfo.radiosInfo,\n\t\t\t    WTPProtocolManager->radiosInfo.radioCount,\n\t\t\t    CWWTPRadioInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tint i;\n\n\tfor (i = 0; i < WTPProtocolManager->radiosInfo.radioCount; i++) {\n\n\t\tWTPProtocolManager->radiosInfo.radiosInfo[i].radioID = i;\n\t\t/*WTPProtocolManager->radiosInfo.radiosInfo[i].stationCount = 0; */\n\t\t/* default value for CAPWAP */\n\t\tWTPProtocolManager->radiosInfo.radiosInfo[i].adminState = ENABLED;\n\t\tWTPProtocolManager->radiosInfo.radiosInfo[i].adminCause = AD_NORMAL;\n\t\tWTPProtocolManager->radiosInfo.radiosInfo[i].operationalState = DISABLED;\n\t\tWTPProtocolManager->radiosInfo.radiosInfo[i].operationalCause = OP_NORMAL;\n\t\tWTPProtocolManager->radiosInfo.radiosInfo[i].TxQueueLevel = 0;\n\t\tWTPProtocolManager->radiosInfo.radiosInfo[i].wirelessLinkFramesPerSec = 0;\n\t}\n\tCWDebugLog(\"Join Request Saved\");\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACMainLoop.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A              *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Daniele De Sanctis (danieledesanctis@gmail.com)                                    *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#include \"CWAC.h\"\n#include \"CWStevens.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/* index of the current thread in the global array */\nCWThreadSpecific gIndexSpecific;\n\nint gCWWaitJoin = CW_WAIT_JOIN_DEFAULT;\n\nCW_THREAD_RETURN_TYPE CWManageWTP(void *arg);\nCW_THREAD_RETURN_TYPE CWManageTimers(void *arg);\nvoid CWCriticalTimerExpiredHandler(int arg);\nvoid CWSoftTimerExpiredHandler(int arg);\n\nvoid CWACManageIncomingPacket(CWSocket sock,\n\t\t\t      unsigned char *buf,\n\t\t\t      int len, int incomingInterfaceIndex, CWNetworkLev4Address * addrPtr, CWBool dataFlag);\nvoid _CWCloseThread(int i);\nvoid CWResetWTPProtocolManager(CWWTPProtocolManager * WTPProtocolManager);\nCWWTPManager *CWWTPByName(const char *addr);\nint CWWTPByAddress(CWNetworkLev4Address * addressPtr, CWSocket sock);\n\nvoid CWACEnterMainLoop()\n{\n\n\tstruct sigaction act;\n\n\tCWLog(\"AC enters in the MAIN_LOOP\");\n\n\n\t/* set signals\n\t * all the thread we spawn will inherit these settings\n\t */\n\n\t/*\n\t * BUG UMR03\n\t *\n\t * 20/10/2009 - Donato Capitella\n\t */\n\tsigemptyset(&act.sa_mask);\n\n\tact.sa_flags = 0;\n\t/* called when a timer requested by the thread has expired */\n\tact.sa_handler = CWCriticalTimerExpiredHandler;\n\tsigaction(CW_CRITICAL_TIMER_EXPIRED_SIGNAL, &act, NULL);\n\n\tact.sa_flags = 0;\n\t/* called when a timer requested by the thread has expired */\n\tact.sa_handler = CWSoftTimerExpiredHandler;\n\tsigaction(CW_SOFT_TIMER_EXPIRED_SIGNAL, &act, NULL);\n\n\t/* signals will be unblocked by the threads that needs timers */\n\tCWThreadSetSignals(SIG_BLOCK, 2, CW_CRITICAL_TIMER_EXPIRED_SIGNAL, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\tif (!(CWThreadCreateSpecific(&gIndexSpecific, NULL))) {\n\t\tCWLog(\"Critical Error With Thread Data\");\n\t\texit(1);\n\t}\n\n\tCWThread thread_interface;\n\tif (!CWErr(CWCreateThread(&thread_interface, CWInterface, NULL))) {\n\t\tCWLog(\"Error starting Interface Thread\");\n\t\texit(1);\n\t}\n\n\tCW_REPEAT_FOREVER {\n\t\t/* CWACManageIncomingPacket will be called\n\t\t * when a new packet is ready to be read\n\t\t */\n\t\tif (!CWErr(CWNetworkUnsafeMultiHomed(&gACSocket, CWACManageIncomingPacket, CW_FALSE)))\n\t\t\texit(1);\n\t}\n}\n\n/* argument passed to the thread func */\ntypedef struct {\n\tint index;\n\tCWSocket sock;\n\tint interfaceIndex;\n} CWACThreadArg;\n\n/*\n * This callback function is called when there is something to read in a\n * CWMultiHomedSocket (see ACMultiHomed.c).\n *\n * Params: sock,    is the socket that can receive the packet and it can be\n *          used to reply.\n *     buf,     (array of len chars) contains the packet which is ready\n *          on the socket's queue (obtained with MSG_PEEK).\n *     incomingInterfaceIndex,  is the index (different from the system\n *                  index, see ACMultiHomed.c) of the interface\n *                  the packet was sent to, in the array returned\n *                  by CWNetworkGetInterfaceAddresses. If the\n *                  packet was sent to a broadcast/multicast address,\n *                  incomingInterfaceIndex is -1.\n */\nvoid CWACManageIncomingPacket(CWSocket sock,\n\t\t\t      unsigned char *buf,\n\t\t\t      int readBytes,\n\t\t\t      int incomingInterfaceIndex, CWNetworkLev4Address * addrPtr, CWBool dataFlag)\n{\n\n\tint WTPIndex = 0;\n\tchar *pData;\n\n\t/* check if sender address is known */\n\tWTPIndex = CWWTPByAddress(addrPtr, sock);\n\n\tif (WTPIndex >= 0) {\n\t\t/* known WTP */\n\t\t/* Clone data packet */\n\t\tCW_CREATE_OBJECT_SIZE_ERR(pData, readBytes, {\n\t\t\t\t\t  CWLog(\"Out Of Memory\");\n\t\t\t\t\t  return;\n\t\t\t\t\t  }\n\t\t);\n\t\tmemcpy(pData, buf, readBytes);\n\n\t\tCWLockSafeList(gWTPs[WTPIndex].packetReceiveList);\n\t\tCWAddElementToSafeListTailwitDataFlag(gWTPs[WTPIndex].packetReceiveList, pData, readBytes, dataFlag);\n\t\tCWUnlockSafeList(gWTPs[WTPIndex].packetReceiveList);\n\t\tif (dataFlag)\n\t\t\tCW_COPY_NET_ADDR_PTR(&(gWTPs[WTPIndex].dataAddress), addrPtr);\n\n\t\t\t\n\t} else {\n\t\t/* unknown WTP */\n\t\tint seqNum;\n\t\tCWDiscoveryRequestValues values;\n\n\t\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex)))\n\t\t\texit(1);\n\n\t\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\t\tif (gActiveWTPs >= gMaxWTPs) {\n\n\t\t\tCWLog(\"Too many WTPs\");\n\t\t\treturn;\n\t\t}\n\t\tCWLog(\"\\n\");\n\n\t\tif (CWErr(CWParseDiscoveryRequestMessage(buf, readBytes, &seqNum, &values))) {\n\n\t\t\tCWProtocolMessage *msgPtr;\n\n\t\t\tCWLog(\"\\n\");\n\t\t\tCWLog(\"######### Discovery State #########\");\n\n\t\t\tCWUseSockNtop(addrPtr, CWLog(\"CAPWAP Discovery Request from %s\", str);\n\t\t\t    );\n\n\t\t\t/* don't add this WTP to our list to minimize DoS\n\t\t\t * attacks (will be added after join)\n\t\t\t */\n\n\t\t\t/* destroy useless values */\n\t\t\tCWDestroyDiscoveryRequestValues(&values);\n\n\t\t\t/* send response to WTP\n\t\t\t * note: we can consider reassembling only changed part\n\t\t\t * AND/OR do this in a new thread.\n\t\t\t */\n\t\t\tif (!CWErr(CWAssembleDiscoveryResponse(&msgPtr, seqNum))) {\n\t\t\t\t/*\n\t\t\t\t * note: maybe an out-of-memory memory error\n\t\t\t\t * can be resolved without exit()-ing by\n\t\t\t\t * killing some thread or doing other funky\n\t\t\t\t * things.\n\t\t\t\t */\n\t\t\t\tCWLog(\"Critical Error Assembling Discovery Response\");\n\t\t\t\texit(1);\n\t\t\t}\n\n\t\t\tif (!CWErr(CWNetworkSendUnsafeUnconnected(sock, addrPtr, (*msgPtr).msg, (*msgPtr).offset))) {\n\n\t\t\t\tCWLog(\"Critical Error Sending Discovery Response\");\n\t\t\t\texit(1);\n\t\t\t}\n\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(*msgPtr);\n\t\t\tCW_FREE_OBJECT(msgPtr);\n\t\t} else {\n\t\t\t/* this isn't a Discovery Request */\n\t\t\tint i;\n\t\t\tCWACThreadArg *argPtr;\n\n\t\t\tCWUseSockNtop(addrPtr, CWDebugLog(\"Possible Client Hello from %s\", str);\n\t\t\t    );\n\n\t\t\tif (!CWErr(CWThreadMutexLock(&gWTPsMutex)))\n\t\t\t\texit(1);\n\t\t\t/* look for the first free slot */\n\t\t\tfor (i = 0; i < gMaxWTPs && gWTPs[i].isNotFree; i++) ;\n\n\t\t\tCW_COPY_NET_ADDR_PTR(&(gWTPs[i].address), addrPtr);\n\t                if (dataFlag)\n                        CW_COPY_NET_ADDR_PTR(&(gWTPs[i].dataAddress), addrPtr);\n\n\t\t\tgWTPs[i].isNotFree = CW_TRUE;\n\t\t\tgWTPs[i].isRequestClose = CW_FALSE;\n\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\t\t\t/* Capwap receive packets list */\n\t\t\tif (!CWErr(CWCreateSafeList(&gWTPs[i].packetReceiveList))) {\n\n\t\t\t\tif (!CWErr(CWThreadMutexLock(&gWTPsMutex)))\n\t\t\t\t\texit(1);\n\t\t\t\tgWTPs[i].isNotFree = CW_FALSE;\n\t\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tCWSetMutexSafeList(gWTPs[i].packetReceiveList, &gWTPs[i].interfaceMutex);\n\t\t\tCWSetConditionSafeList(gWTPs[i].packetReceiveList, &gWTPs[i].interfaceWait);\n\n\t\t\tCW_CREATE_OBJECT_ERR(argPtr, CWACThreadArg, {\n\t\t\t\t\t     CWLog(\"Out Of Memory\");\n\t\t\t\t\t     return;\n\t\t\t\t\t     }\n\t\t\t);\n\n\t\t\targPtr->index = i;\n\t\t\targPtr->sock = sock;\n\t\t\targPtr->interfaceIndex = incomingInterfaceIndex;\n\n\t\t\t/*\n\t\t\t * If the packet was addressed to a broadcast address,\n\t\t\t * just choose an interface we like (note: we can consider\n\t\t\t * a bit load balancing instead of hard-coding 0-indexed\n\t\t\t * interface). Btw, Join Request should not really be\n\t\t\t * accepted if addressed to a broadcast address, so we\n\t\t\t * could simply discard the packet and go on.\n\t\t\t * If you leave this code, the WTP Count will increase\n\t\t\t * for the interface we hard-code here, even if it is not\n\t\t\t * necessary the interface we use to send packets to that\n\t\t\t * WTP. If we really want to accept Join Request from\n\t\t\t * broadcast address, we can consider asking to the kernel\n\t\t\t * which interface will be used to send the packet to a\n\t\t\t * specific address (if it remains the same) and than\n\t\t\t * increment WTPCount for that interface instead of 0-indexed one.\n\t\t\t */\n\t\t\tif (argPtr->interfaceIndex < 0)\n\t\t\t\targPtr->interfaceIndex = 0;\n\n\t\t\t/* create the thread that will manage this WTP */\n\t\t\tif (!CWErr(CWCreateThread(&(gWTPs[i].thread), CWManageWTP, argPtr))) {\n\n\t\t\t\tCW_FREE_OBJECT(argPtr);\n\t\t\t\tif (!CWErr(CWThreadMutexLock(&gWTPsMutex)))\n\t\t\t\t\texit(1);\n\n\t\t\t\tCWDestroySafeList(&gWTPs[i].packetReceiveList);\n\t\t\t\tgWTPs[i].isNotFree = CW_FALSE;\n\t\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/* Clone data packet */\n\t\t\tCW_CREATE_OBJECT_SIZE_ERR(pData, readBytes, {\n\t\t\t\t\t\t  CWLog(\"Out Of Memory\");\n\t\t\t\t\t\t  return;\n\t\t\t\t\t\t  }\n\t\t\t);\n\t\t\tmemcpy(pData, buf, readBytes);\n\n\t\t\tCWLockSafeList(gWTPs[i].packetReceiveList);\n\t\t\tCWAddElementToSafeListTailwitDataFlag(gWTPs[i].packetReceiveList, pData, readBytes, dataFlag);\n\t\t\tCWUnlockSafeList(gWTPs[i].packetReceiveList);\n\t\t}\n\t}\n}\n\n/*\n * Simple job: see if we have a thread that is serving address *addressPtr\n */\n__inline__ int CWWTPByAddress(CWNetworkLev4Address * addressPtr, CWSocket sock)\n{\n\n\tint i;\n\tif (addressPtr == NULL)\n\t\treturn -1; \n\n\tCWThreadMutexLock(&gWTPsMutex);\n\tfor (i = 0; i < gMaxWTPs; i++) {\n\n\t\tif (gWTPs[i].isNotFree &&\n\t\t    &(gWTPs[i].address) != NULL &&\n\t\t    !sock_cmp_addr((struct sockaddr *)addressPtr,\n\t\t\t\t   (struct sockaddr *)&(gWTPs[i].address), sizeof(CWNetworkLev4Address))) {\n\n\t\t\t/* we treat a WTP that sends packet to a different\n\t\t\t * AC's interface as a new WTP\n\t\t\t */\n\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\t\t\treturn i;\n\t\t}\n\t}\n\n\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\treturn -1;\n}\n\n/*\n * Session's thread function: each thread will manage a single session\n * with one WTP.\n */\nCW_THREAD_RETURN_TYPE CWManageWTP(void *arg)\n{\n\n\tint i = ((CWACThreadArg *) arg)->index;\n\tCWSocket sock = ((CWACThreadArg *) arg)->sock;\n\tint interfaceIndex = ((CWACThreadArg *) arg)->interfaceIndex;\n\n\tCW_FREE_OBJECT(arg);\n\n\tif (!(CWThreadSetSpecific(&gIndexSpecific, &i))) {\n\n\t\tCWLog(\"Critical Error with Thread Data\");\n\t\t_CWCloseThread(i);\n\t}\n\n\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex)))\n\t\texit(1);\n\n\tgActiveWTPs++;\n\n\tgInterfaces[interfaceIndex].WTPCount++;\n\tCWUseSockNtop(((struct sockaddr *)&(gInterfaces[interfaceIndex].addr)),\n\t\t      CWDebugLog(\"One more WTP on %s (%d)\", str, interfaceIndex););\n\n\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\tCWACInitBinding(i);\n\n\tgWTPs[i].interfaceIndex = interfaceIndex;\n\tgWTPs[i].socket = sock;\n\n\tgWTPs[i].fragmentsList = NULL;\n\t/* we're in the join state for this session */\n\tgWTPs[i].currentState = CW_ENTER_JOIN;\n\tgWTPs[i].subState = CW_DTLS_HANDSHAKE_IN_PROGRESS;\n\n\t/**** ACInterface ****/\n\tgWTPs[i].interfaceCommandProgress = CW_FALSE;\n\tgWTPs[i].interfaceCommand = NO_CMD;\n\tCWDestroyThreadMutex(&gWTPs[i].interfaceMutex);\n\tCWCreateThreadMutex(&gWTPs[i].interfaceMutex);\n\tCWDestroyThreadMutex(&gWTPs[i].interfaceSingleton);\n\tCWCreateThreadMutex(&gWTPs[i].interfaceSingleton);\n\tCWDestroyThreadCondition(&gWTPs[i].interfaceWait);\n\tCWCreateThreadCondition(&gWTPs[i].interfaceWait);\n\tCWDestroyThreadCondition(&gWTPs[i].interfaceComplete);\n\tCWCreateThreadCondition(&gWTPs[i].interfaceComplete);\n\tgWTPs[i].qosValues = NULL;\n\t/**** ACInterface ****/\n\n\tgWTPs[i].messages = NULL;\n\tgWTPs[i].messagesCount = 0;\n\tgWTPs[i].isRetransmitting = CW_FALSE;\n\tgWTPs[i].retransmissionCount = 0;\n\n\tCWResetWTPProtocolManager(&(gWTPs[i].WTPProtocolManager));\n\n\tCWLog(\"New Session\");\n\n\t/* start WaitJoin timer */\n\tif (!CWErr(CWTimerRequest(gCWWaitJoin,\n\t\t\t\t  &(gWTPs[i].thread), &(gWTPs[i].currentTimer), CW_CRITICAL_TIMER_EXPIRED_SIGNAL))) {\n\n\t\tCWCloseThread();\n\t}\n#ifndef CW_NO_DTLS\n\tCWDebugLog(\"Init DTLS Session\");\n\n\tif (!CWErr(CWSecurityInitSessionServer(&gWTPs[i],\n\t\t\t\t\t       sock, gACSecurityContext, &((gWTPs[i]).session), &(gWTPs[i].pathMTU)))) {\n\n\t\tCWTimerCancel(&(gWTPs[i].currentTimer));\n\t\tCWCloseThread();\n\t}\n#endif\n\t(gWTPs[i]).subState = CW_WAITING_REQUEST;\n\n\tif (gCWForceMTU > 0)\n\t\tgWTPs[i].pathMTU = gCWForceMTU;\n\n\tCWDebugLog(\"Path MTU for this Session: %d\", gWTPs[i].pathMTU);\n\n\tCW_REPEAT_FOREVER {\n\t\tint readBytes;\n\t\tCWProtocolMessage msg;\n\t\tCWBool dataFlag = CW_FALSE;\n\n\t\tmsg.msg = NULL;\n\t\tmsg.offset = 0;\n\n\t\t/* Wait WTP action */\n\n\t\tCWThreadMutexLock(&gWTPs[i].interfaceMutex);\n\n\t\twhile ((gWTPs[i].isRequestClose == CW_FALSE) &&\n\t\t       (CWGetCountElementFromSafeList(gWTPs[i].packetReceiveList) == 0) &&\n\t\t       (gWTPs[i].interfaceCommand == NO_CMD)) {\n\n\t\t\t/*TODO: Check system */\n\t\t\tCWWaitThreadCondition(&gWTPs[i].interfaceWait, &gWTPs[i].interfaceMutex);\n\t\t}\n\n\t\tCWThreadMutexUnlock(&gWTPs[i].interfaceMutex);\n\n\t\tif (gWTPs[i].isRequestClose) {\n\n\t\t\tCWLog(\"Request close thread\");\n\t\t\t_CWCloseThread(i);\n\t\t}\n\n\t\tCWThreadSetSignals(SIG_BLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\n\t\tif (CWGetCountElementFromSafeList(gWTPs[i].packetReceiveList) > 0) {\n\n\t\t\tCWBool bCrypt = CW_FALSE;\n\t\t\tchar *pBuffer;\n\n\t\t\tCWThreadMutexLock(&gWTPs[i].interfaceMutex);\n\t\t\tpBuffer = (char *)CWGetHeadElementFromSafeList(gWTPs[i].packetReceiveList, NULL);\n\n\t\t\tif (((pBuffer[0] & 0x0f) == CW_PACKET_CRYPT) && ((gWTPs[i].buf[0] & 0x0f) == CW_PACKET_CRYPT))\n\t\t\t\tbCrypt = CW_TRUE;\n\n\t\t\tCWThreadMutexUnlock(&gWTPs[i].interfaceMutex);\n\n\t\t\tif (bCrypt) {\n#ifndef CW_NO_DTLS\n\t\t\t\tif (!CWErr(CWSecurityReceive(gWTPs[i].session,\n\t\t\t\t\t\t\t     gWTPs[i].buf, CW_BUFFER_SIZE - 1, &readBytes))) {\n\t\t\t\t\t/* error */\n\n\t\t\t\t\tCWDebugLog(\"Error during security receive\");\n\t\t\t\t\tCWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n#else\n\t\t\t\tCWDebugLog(\"CAPWAP DTLS in not supported\");\n\t\t\t\tCWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\t\t\t\tcontinue;\n#endif\n\t\t\t} else {\n\t\t\t\tCWThreadMutexLock(&gWTPs[i].interfaceMutex);\n\t\t\t\tpBuffer =\n\t\t\t\t    (char *)CWRemoveHeadElementFromSafeListwithDataFlag(gWTPs[i].packetReceiveList,\n\t\t\t\t\t\t\t\t\t\t\t&readBytes, &dataFlag);\n\t\t\t\tCWThreadMutexUnlock(&gWTPs[i].interfaceMutex);\n\n\t\t\t\tmemcpy(gWTPs[i].buf, pBuffer, readBytes);\n\t\t\t\tCW_FREE_OBJECT(pBuffer);\n\t\t\t}\n\n\t\t\tif (!CWProtocolParseFragment(gWTPs[i].buf,\n\t\t\t\t\t\t     readBytes,\n\t\t\t\t\t\t     &(gWTPs[i].fragmentsList), &msg, &dataFlag, gWTPs[i].RadioMAC)) {\n\n\t\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_NEED_RESOURCE) {\n\n\t\t\t\t\tCWDebugLog(\"Need At Least One More Fragment\");\n\t\t\t\t} else {\n\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t}\n\t\t\t\tCWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tswitch (gWTPs[i].currentState) {\n\t\t\tcase CW_ENTER_JOIN:{\n\t\t\t\t\t/* we're inside the join state */\n\t\t\t\t\tif (!ACEnterJoin(i, &msg)) {\n\t\t\t\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_INVALID_FORMAT) {\n\t\t\t\t\t\t\t/* Log and ignore other messages */\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWLog(\"Received something different from a Join Request\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/* critical error, close session */\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWThreadSetSignals(SIG_UNBLOCK, 1,\n\t\t\t\t\t\t\t\t\t   CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\t\t\t\t\t\t\tCWCloseThread();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tcase CW_ENTER_CONFIGURE:{\n\t\t\t\t\tif (!ACEnterConfigure(i, &msg)) {\n\t\t\t\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_INVALID_FORMAT) {\n\t\t\t\t\t\t\t/* Log and ignore other messages */\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWLog(\"Received something different from a Configure Request\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/* critical error, close session */\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWThreadSetSignals(SIG_UNBLOCK, 1,\n\t\t\t\t\t\t\t\t\t   CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\t\t\t\t\t\t\tCWCloseThread();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tcase CW_ENTER_DATA_CHECK:{\n\t\t\t\t\tif (!ACEnterDataCheck(i, &msg)) {\n\t\t\t\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_INVALID_FORMAT) {\n\t\t\t\t\t\t\t/* Log and ignore other messages */\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWLog\n\t\t\t\t\t\t\t    (\"Received something different from a Change State Event Request\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/* critical error, close session */\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWThreadSetSignals(SIG_UNBLOCK, 1,\n\t\t\t\t\t\t\t\t\t   CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\t\t\t\t\t\t\tCWCloseThread();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tcase CW_ENTER_RUN:{\n\t\t\t\t\tif (!ACEnterRun(i, &msg, dataFlag)) {\n\t\t\t\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_INVALID_FORMAT) {\n\t\t\t\t\t\t\t/* Log and ignore other messages */\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWLog\n\t\t\t\t\t\t\t    (\"--> Received something different from a valid Run Message\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/* critical error, close session */\n\t\t\t\t\t\t\tCWLog(\"--> Critical Error... closing thread\");\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\tCWThreadSetSignals(SIG_UNBLOCK, 1,\n\t\t\t\t\t\t\t\t\t   CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\t\t\t\t\t\t\tCWCloseThread();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tdefault:{\n\t\t\t\t\tCWLog(\"Not Handled Packet\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t} else {\n\n\t\t\tCWThreadMutexLock(&gWTPs[i].interfaceMutex);\n\n\t\t\tif (gWTPs[i].interfaceCommand != NO_CMD) {\n\n\t\t\t\tCWBool bResult = CW_FALSE;\n\n\t\t\t\tswitch (gWTPs[i].interfaceCommand) {\n\t\t\t\tcase QOS_CMD:{\n\t\t\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\t\t\t/* CWDebugLog(\"~~~~~~seq num in Check: %d~~~~~~\", seqNum); */\n\t\t\t\t\t\tif (CWAssembleConfigurationUpdateRequest(&(gWTPs[i].messages),\n\t\t\t\t\t\t\t\t\t\t\t &(gWTPs[i].messagesCount),\n\t\t\t\t\t\t\t\t\t\t\t gWTPs[i].pathMTU,\n\t\t\t\t\t\t\t\t\t\t\t seqNum,\n\t\t\t\t\t\t\t\t\t\t\t CONFIG_UPDATE_REQ_QOS_ELEMENT_TYPE))\n\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t\t\t    (i, CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE, seqNum))\n\t\t\t\t\t\t\t\tbResult = CW_TRUE;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCWACStopRetransmission(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CLEAR_CONFIG_MSG_CMD:{\n\t\t\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\t\t\t/* Clear Configuration Request */\n\t\t\t\t\t\tif (CWAssembleClearConfigurationRequest(&(gWTPs[i].messages),\n\t\t\t\t\t\t\t\t\t\t\t&(gWTPs[i].messagesCount),\n\t\t\t\t\t\t\t\t\t\t\tgWTPs[i].pathMTU, seqNum)) {\n\n\t\t\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t\t\t    (i, CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_RESPONSE, seqNum))\n\t\t\t\t\t\t\t\tbResult = CW_TRUE;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCWACStopRetransmission(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t/********************************************************\n\t\t\t\t * 2009 Update:                                         *\n\t\t\t\t *              New switch case for OFDM_CONTROL_CMD    *\n\t\t\t\t ********************************************************/\n\n\t\t\t\tcase OFDM_CONTROL_CMD:{\n\t\t\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\t\t\tif (CWAssembleConfigurationUpdateRequest(&(gWTPs[i].messages),\n\t\t\t\t\t\t\t\t\t\t\t &(gWTPs[i].messagesCount),\n\t\t\t\t\t\t\t\t\t\t\t gWTPs[i].pathMTU,\n\t\t\t\t\t\t\t\t\t\t\t seqNum,\n\t\t\t\t\t\t\t\t\t\t\t CONFIG_UPDATE_REQ_OFDM_ELEMENT_TYPE))\n\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t\t\t    (i, CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE, seqNum))\n\t\t\t\t\t\t\t\tbResult = CW_TRUE;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCWACStopRetransmission(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t/*Update 2009\n\t\t\t\t\t   Added case to manage UCI configuration command */\n\t\t\t\tcase UCI_CONTROL_CMD:{\n\t\t\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\t\t\tif (CWAssembleConfigurationUpdateRequest(&(gWTPs[i].messages),\n\t\t\t\t\t\t\t\t\t\t\t &(gWTPs[i].messagesCount),\n\t\t\t\t\t\t\t\t\t\t\t gWTPs[i].pathMTU,\n\t\t\t\t\t\t\t\t\t\t\t seqNum,\n\t\t\t\t\t\t\t\t\t\t\t CONFIG_UPDATE_REQ_VENDOR_UCI_ELEMENT_TYPE))\n\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t\t\t    (i, CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE, seqNum))\n\t\t\t\t\t\t\t\tbResult = CW_TRUE;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCWACStopRetransmission(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase WTP_UPDATE_CMD:{\n\t\t\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\t\t\tif (CWAssembleConfigurationUpdateRequest(&(gWTPs[i].messages),\n\t\t\t\t\t\t\t\t\t\t\t &(gWTPs[i].messagesCount),\n\t\t\t\t\t\t\t\t\t\t\t gWTPs[i].pathMTU,\n\t\t\t\t\t\t\t\t\t\t\t seqNum,\n\t\t\t\t\t\t\t\t\t\t\t CONFIG_UPDATE_REQ_VENDOR_WUM_ELEMENT_TYPE))\n\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t\t\t    (i, CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE, seqNum))\n\t\t\t\t\t\t\t\tbResult = CW_TRUE;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCWACStopRetransmission(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tgWTPs[i].interfaceCommand = NO_CMD;\n\n\t\t\t\tif (bResult)\n\t\t\t\t\tgWTPs[i].interfaceCommandProgress = CW_TRUE;\n\t\t\t\telse {\n\t\t\t\t\tgWTPs[i].interfaceResult = 0;\n\t\t\t\t\tCWSignalThreadCondition(&gWTPs[i].interfaceComplete);\n\t\t\t\t\tCWDebugLog(\"Error sending command\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tCWThreadMutexUnlock(&gWTPs[i].interfaceMutex);\n\t\t}\n\t\tCWThreadSetSignals(SIG_UNBLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\t}\n}\n\nvoid _CWCloseThread(int i)\n{\n\n\tCWThreadSetSignals(SIG_BLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\n\t/**** ACInterface ****/\n\tgWTPs[i].qosValues = NULL;\n\tCWThreadMutexUnlock(&(gWTPs[i].interfaceMutex));\n\t/**** ACInterface ****/\n\n\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex)))\n\t\texit(1);\n\n\tgInterfaces[gWTPs[i].interfaceIndex].WTPCount--;\n\tgActiveWTPs--;\n\n\tCWUseSockNtop(((struct sockaddr *)&(gInterfaces[gWTPs[i].interfaceIndex].addr)),\n\t\t      CWLog(\"Remove WTP on Interface %s (%d)\", str, gWTPs[i].interfaceIndex);\n\t    );\n\n\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\tCWDebugLog(\"Close Thread: %08x\", (unsigned int)CWThreadSelf());\n\n#ifndef CW_NO_DTLS\n\tif (gWTPs[i].subState != CW_DTLS_HANDSHAKE_IN_PROGRESS) {\n\n\t\tCWSecurityDestroySession(gWTPs[i].session);\n\t}\n#endif\n\n\t/* this will do nothing if the timer isn't active */\n\tCWTimerCancel(&(gWTPs[i].currentTimer));\n\tCWACStopRetransmission(i);\n\n\tif (gWTPs[i].interfaceCommandProgress == CW_TRUE) {\n\n\t\tCWThreadMutexLock(&gWTPs[i].interfaceMutex);\n\n\t\tgWTPs[i].interfaceResult = 1;\n\t\tgWTPs[i].interfaceCommandProgress = CW_FALSE;\n\t\tCWSignalThreadCondition(&gWTPs[i].interfaceComplete);\n\n\t\tCWThreadMutexUnlock(&gWTPs[i].interfaceMutex);\n\t}\n\n\tgWTPs[i].session = NULL;\n\tgWTPs[i].subState = CW_DTLS_HANDSHAKE_IN_PROGRESS;\n\tCWDeleteList(&(gWTPs[i].fragmentsList), CWProtocolDestroyFragment);\n\n\t/* CW_FREE_OBJECT(gWTPs[i].configureReqValuesPtr); */\n\n\tCWCleanSafeList(gWTPs[i].packetReceiveList, free);\n\tCWDestroySafeList(gWTPs[i].packetReceiveList);\n\n\tCWThreadMutexLock(&gWTPsMutex);\n\tgWTPs[i].isNotFree = CW_FALSE;\n\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\tCWExitThread();\n}\n\nvoid CWCloseThread()\n{\n\n\tint *iPtr;\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\n\t\tCWLog(\"Error Closing Thread\");\n\t\treturn;\n\t}\n\n\t_CWCloseThread(*iPtr);\n}\n\nvoid CWCriticalTimerExpiredHandler(int arg)\n{\n\n\tint *iPtr;\n\n\tCWThreadSetSignals(SIG_BLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\n\tCWDebugLog(\"Critical Timer Expired for Thread: %08x\", (unsigned int)CWThreadSelf());\n\tCWDebugLog(\"Abort Session\");\n\t/* CWCloseThread(); */\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\n\t\tCWLog(\"Error Handling Critical timer\");\n\t\tCWThreadSetSignals(SIG_UNBLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\t\treturn;\n\t}\n\n\t/* Request close thread */\n\tgWTPs[*iPtr].isRequestClose = CW_TRUE;\n\tCWSignalThreadCondition(&gWTPs[*iPtr].interfaceWait);\n}\n\nvoid CWSoftTimerExpiredHandler(int arg)\n{\n\n\tint *iPtr;\n\n\tCWThreadSetSignals(SIG_BLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\n\tCWDebugLog(\"Soft Timer Expired for Thread: %08x\", (unsigned int)CWThreadSelf());\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\n\t\tCWLog(\"Error Handling Soft timer\");\n\t\tCWThreadSetSignals(SIG_UNBLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\t\treturn;\n\t}\n\n\tif ((!gWTPs[*iPtr].isRetransmitting) || (gWTPs[*iPtr].messages == NULL)) {\n\n\t\tCWDebugLog(\"Soft timer expired but we are not retransmitting\");\n\t\tCWThreadSetSignals(SIG_UNBLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n\t\treturn;\n\t}\n\n\t(gWTPs[*iPtr].retransmissionCount)++;\n\n\tCWDebugLog(\"Retransmission Count increases to %d\", gWTPs[*iPtr].retransmissionCount);\n\n\tif (gWTPs[*iPtr].retransmissionCount >= gCWMaxRetransmit) {\n\t\tCWDebugLog(\"Peer is Dead\");\n\t\t/* ?? _CWCloseThread(*iPtr);\n\t\t * Request close thread\n\t\t */\n\t\tgWTPs[*iPtr].isRequestClose = CW_TRUE;\n\t\tCWSignalThreadCondition(&gWTPs[*iPtr].interfaceWait);\n\t\treturn;\n\t}\n\n\tif (!CWErr(CWACResendAcknowledgedPacket(*iPtr))) {\n\t\t_CWCloseThread(*iPtr);\n\t}\n\n\t/* CWDebugLog(\"~~~~~~fine ritrasmissione ~~~~~\"); */\n\tCWThreadSetSignals(SIG_UNBLOCK, 2, CW_SOFT_TIMER_EXPIRED_SIGNAL, CW_CRITICAL_TIMER_EXPIRED_SIGNAL);\n}\n\nvoid CWResetWTPProtocolManager(CWWTPProtocolManager * WTPProtocolManager)\n{\n\n\tCW_FREE_OBJECT(WTPProtocolManager->locationData);\n\tCW_FREE_OBJECT(WTPProtocolManager->name);\n\tWTPProtocolManager->sessionID = 0;\n\tWTPProtocolManager->descriptor.maxRadios = 0;\n\tWTPProtocolManager->descriptor.radiosInUse = 0;\n\tWTPProtocolManager->descriptor.encCapabilities.encryptCapsCount = 0;\n\tCW_FREE_OBJECT(WTPProtocolManager->descriptor.encCapabilities.encryptCaps);\n\tWTPProtocolManager->descriptor.vendorInfos.vendorInfosCount = 0;\n\tCW_FREE_OBJECT(WTPProtocolManager->descriptor.vendorInfos.vendorInfos);\n\n\tWTPProtocolManager->radiosInfo.radioCount = 0;\n\tCW_FREE_OBJECT(WTPProtocolManager->radiosInfo.radiosInfo);\n\tCW_FREE_OBJECT(WTPProtocolManager->ACName);\n\t(WTPProtocolManager->ACNameIndex).count = 0;\n\tCW_FREE_OBJECT((WTPProtocolManager->ACNameIndex).ACNameIndex);\n\t(WTPProtocolManager->radioAdminInfo).radiosCount = 0;\n\tCW_FREE_OBJECT((WTPProtocolManager->radioAdminInfo).radios);\n\tWTPProtocolManager->StatisticsTimer = 0;\n\t(WTPProtocolManager->WTPBoardData).vendorInfosCount = 0;\n\tCW_FREE_OBJECT((WTPProtocolManager->WTPBoardData).vendorInfos);\n\tCW_FREE_OBJECT(WTPProtocolManager->WTPRebootStatistics);\n\n\t//CWWTPResetRebootStatistics(&(WTPProtocolManager->WTPRebootStatistics));\n\n\t/*\n\t **mancano questi campi:**\n\t CWNetworkLev4Address address;\n\t int pathMTU;\n\t struct sockaddr_in ipv4Address;\n\t CWProtocolConfigureRequestValues *configureReqValuesPtr;\n\t CWTimerID currentPacketTimer;\n\t */\n}\n"
  },
  {
    "path": "ACMultiHomedSocket.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#include \"common.h\"\n#include \"ieee802_11_defs.h\"\n\n#define TYPE_LEN 2\n#define ETH_ALEN 6\n#define ETH_HLEN 14\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nvoid CWNetworkDeleteMHInterface(void *intPtr)\n{\n\n\tCW_FREE_OBJECT(intPtr);\n}\n\nint from_8023_to_80211(unsigned char *inbuffer, int inlen, unsigned char *outbuffer, unsigned char *own_addr)\n{\n\n\tint indx = 0;\n\tstruct ieee80211_hdr hdr;\n\tos_memset(&hdr, 0, sizeof(struct ieee80211_hdr));\n\n\thdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA) | host_to_le16(WLAN_FC_FROMDS);\n\thdr.duration_id = 0;\n\thdr.seq_ctrl = 0;\n\n\tos_memcpy(hdr.addr1, inbuffer, ETH_ALEN);\n\tos_memcpy(hdr.addr2, own_addr, ETH_ALEN);\n\tos_memcpy(hdr.addr3, inbuffer + ETH_ALEN, ETH_ALEN);\n\n\tos_memcpy(outbuffer + indx, &hdr, sizeof(hdr));\n\tindx += sizeof(hdr);\n\tos_memcpy(outbuffer + indx, inbuffer, inlen);\n\tindx += inlen;\n\n\treturn indx;\n}\n\n/*\n * Multihomed sockets maps the system index for each interface to a array-like\n * int index in range 0-(# of interfaces -1). This function returns the int\n * index given the system index of an interface managed by the given multihomed\n * socket.\n */\nint CWNetworkGetInterfaceIndexFromSystemIndex(CWMultiHomedSocket * sockPtr, int systemIndex)\n{\n\n\tint i, c;\n\n\tif (sockPtr == NULL || systemIndex == -1)\n\t\treturn -1;\n\n\tfor (i = 0, c = 0; i < sockPtr->count; i++) {\n\n\t\tif (sockPtr->interfaces[i].kind == CW_PRIMARY) {\n\n\t\t\t/* each primary interface increments the int index */\n\t\t\tif (sockPtr->interfaces[i].systemIndex == systemIndex)\n\t\t\t\treturn c;\n\t\t\tc++;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/*\n * Check if the interface with system index systemIndex is already managed by\n * the multihomed socket. If the answer is yes, returns informations on that\n * interface, returns NULL otherwise.\n */\nCWMultiHomedInterface *CWNetworkGetInterfaceAlreadyStored(CWList list, short systemIndex)\n{\n\n\tCWListElement *el;\n\n\tfor (el = list; el != NULL; el = el->next) {\n\n\t\tif (((CWMultiHomedInterface *) (el->data))->systemIndex == systemIndex &&\n\t\t    ((CWMultiHomedInterface *) (el->data))->kind == CW_PRIMARY)\n\n\t\t\treturn (CWMultiHomedInterface *) el->data;\n\t}\n\treturn NULL;\n}\n\n/*\n * Init multihomed socket. Will bind a socket for each interface + each\n * broadcast address + the wildcard addres + each multicast address in\n * multicastGroups.\n */\nCWBool CWNetworkInitSocketServerMultiHomed(CWMultiHomedSocket * sockPtr,\n\t\t\t\t\t   int port, char **multicastGroups, int multicastGroupsCount)\n{\n\n\tstruct ifi_info *ifi, *ifihead;\n\tCWNetworkLev4Address wildaddr;\n\tint yes = 1;\n\tCWSocket sock;\n\tCWMultiHomedInterface *p;\n\tCWList interfaceList = CW_LIST_INIT;\n\tCWListElement *el = NULL;\n\tint i;\n\n\tif (sockPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tsockPtr->count = 0;\n\n\t/*\n\t * note: if get_ifi_info is called with AF_INET6 on an host that doesn't\n\t * support IPv6, it'll simply act like if it was called with AF_INET.\n\t * Consider aliases as different interfaces (last arg of get_ifi_info is 1).\n\t * Why? Just to increase the funny side of the thing.\n\t */\n#ifdef CW_DEBUGGING\n\t/* for each network interface... */\n\tfor (ifihead = ifi = get_ifi_info((gNetworkPreferredFamily == CW_IPv6) ? AF_INET6 : AF_INET, 1); ifi != NULL;\n\t     ifi = ifi->ifi_next) {\n#else\n\t/* for each network interface... */\n\tfor (ifihead = ifi = get_ifi_info((gNetworkPreferredFamily == CW_IPv6) ? AF_INET6 : AF_INET, 0); ifi != NULL;\n\t     ifi = ifi->ifi_next) {\n#endif\n\t\t/* bind a unicast address */\n\t\tif ((sock = socket(ifi->ifi_addr->sa_family, SOCK_DGRAM, 0)) < 0) {\n\n\t\t\tfree_ifi_info(ifihead);\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t}\n\n\t\t/* reuse address */\n\t\tsetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));\n\n\t\t/* bind address */\n\t\tsock_set_port_cw(ifi->ifi_addr, htons(port));\n\n\t\tif (bind\n\t\t    (sock, (struct sockaddr *)ifi->ifi_addr,\n\t\t     CWNetworkGetAddressSize((CWNetworkLev4Address *) ifi->ifi_addr)) < 0) {\n\n\t\t\tclose(sock);\n\t\t\tCWUseSockNtop(ifi->ifi_addr, CWDebugLog(\"failed %s\", str);\n\t\t\t    );\n\t\t\tcontinue;\n\t\t\t/* CWNetworkRaiseSystemError(CW_ERROR_CREATING); */\n\t\t}\n\n\t\tCWUseSockNtop(ifi->ifi_addr, CWLog(\"bound %s (%d, %s)\", str, ifi->ifi_index, ifi->ifi_name);\n\t\t    );\n\n\t\t/* store socket inside multihomed socket */\n\t\tCW_CREATE_OBJECT_ERR(p, CWMultiHomedInterface, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tp->sock = sock;\n\t\tif (CWNetworkGetInterfaceAlreadyStored(interfaceList, ifi->ifi_index) == NULL &&\n\t\t    strncmp(ifi->ifi_name, \"lo\", 2)) {\n\t\t\t/* don't consider loopback an interface\n\t\t\t   (even if we accept packets from loopback) */\n\t\t\tCWDebugLog(\"Primary Address\");\n\t\t\tp->kind = CW_PRIMARY;\n\n\t\t} else {\n\t\t\t/* should be BROADCAST_OR_ALIAS_OR_MULTICAST_OR_LOOPBACK ;-) */\n\t\t\tp->kind = CW_BROADCAST_OR_ALIAS;\n#ifdef CW_DEBUGGING\n#if 0\n\t\t\tif (!strncmp(ifi->ifi_name, \"lo\", 2)) {\n\t\t\t\tp->kind = CW_PRIMARY;\n\t\t\t}\n#endif\n#endif\n\t\t}\n\n\t\tp->systemIndex = ifi->ifi_index;\n\n\t\t/* the next field is useful only if we are an IPv6 server. In\n\t\t * this case, p->addr contains the IPv6 address of the interface\n\t\t * and p->addrIPv4 contains the equivalent IPv4 address. On the\n\t\t * other side, if we are an IPv4 server p->addr contains the\n\t\t * IPv4 address of the interface and p->addrIPv4 is garbage.\n\t\t */\n\t\tp->addrIPv4.ss_family = AF_UNSPEC;\n\n\t\tCW_COPY_NET_ADDR_PTR(&(p->addr), ifi->ifi_addr);\n\t\t// Todd: Bind data channel to port 5427\n\t\t/* bind a unicast address of data UDP stream */\n\t\tif ((sock = socket(ifi->ifi_addr->sa_family, SOCK_DGRAM, 0)) < 0) {\n\t\t\tfree_ifi_info(ifihead);\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t}\n\n\t\t/* reuse address */\n\t\tsetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));\n\n\t\t/* bind address */\n\t\tsock_set_port_cw(ifi->ifi_addr, htons(port + 1));\n\n\t\tif (bind\n\t\t    (sock, (struct sockaddr *)ifi->ifi_addr,\n\t\t     CWNetworkGetAddressSize((CWNetworkLev4Address *) ifi->ifi_addr)) < 0) {\n\t\t\tclose(sock);\n\t\t\tCWUseSockNtop(ifi->ifi_addr, CWDebugLog(\"failed %s\", str);\n\t\t\t    );\n\t\t\tcontinue;\n\t\t\t/* CWNetworkRaiseSystemError(CW_ERROR_CREATING); */\n\t\t}\n\n\t\tCWUseSockNtop(ifi->ifi_addr,\n\t\t\t      CWLog(\"Data channel bound %s (%d, %s)\", str, ifi->ifi_index, ifi->ifi_name);\n\t\t    );\n\n\t\tCW_COPY_NET_ADDR_PTR(&(p->dataAddr), ifi->ifi_addr);\n\t\tp->dataSock = sock;\n\n\t\tif (!CWAddElementToList(&interfaceList, p)) {\n\n\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t}\n\t\t/* we add a socket to the multihomed socket */\n\t\tsockPtr->count++;\n\n\t\tif (ifi->ifi_flags & IFF_BROADCAST) {\n\t\t\t/* try to bind broadcast address */\n\t\t\tif ((sock = socket(ifi->ifi_addr->sa_family, SOCK_DGRAM, 0)) < 0) {\n\n\t\t\t\tfree_ifi_info(ifihead);\n\t\t\t\tCWDeleteList(&interfaceList, CWNetworkDeleteMHInterface);\n\t\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t\t}\n\n\t\t\t/* reuse address */\n\t\t\tsetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));\n\n\t\t\tsock_set_port_cw(ifi->ifi_brdaddr, htons(port));\n\n\t\t\tif (bind(sock, (struct sockaddr *)ifi->ifi_brdaddr,\n\t\t\t\t CWNetworkGetAddressSize((CWNetworkLev4Address *) ifi->ifi_brdaddr)) < 0) {\n\n\t\t\t\tclose(sock);\n\t\t\t\tif (errno == EADDRINUSE) {\n\t\t\t\t\tCWUseSockNtop(ifi->ifi_brdaddr, CWDebugLog(\"EADDRINUSE: %s\", str););\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tCWUseSockNtop(ifi->ifi_brdaddr, CWDebugLog(\"failed %s\", str););\n\t\t\t\t\tcontinue;\n\t\t\t\t\t/* CWDeleteList(&interfaceList, CWNetworkDeleteMHInterface); */\n\t\t\t\t\t/* CWNetworkRaiseSystemError(CW_ERROR_CREATING); */\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tCWUseSockNtop(ifi->ifi_brdaddr, CWLog(\"bound %s (%d, %s)\", str, ifi->ifi_index, ifi->ifi_name);\n\t\t\t    );\n\n\t\t\t/* store socket inside multihomed socket */\n\n\t\t\tCW_CREATE_OBJECT_ERR(p, CWMultiHomedInterface,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tp->sock = sock;\n\t\t\tp->kind = CW_BROADCAST_OR_ALIAS;\n\t\t\tp->systemIndex = ifi->ifi_index;\n\t\t\tCW_COPY_NET_ADDR_PTR(&(p->addr), ifi->ifi_brdaddr);\n\n\t\t\t/* The next field is useful only if we are an IPv6 server.\n\t\t\t * In this case, p->addr contains the IPv6 address of the\n\t\t\t * interface and p->addrIPv4 contains the equivalent IPv4\n\t\t\t * address. On the other side, if we are an IPv4 server\n\t\t\t * p->addr contains the IPv4 address of the interface and\n\t\t\t * p->addrIPv4 is garbage.\n\t\t\t */\n\t\t\tp->addrIPv4.ss_family = AF_UNSPEC;\n\n\t\t\tif (!CWAddElementToList(&interfaceList, p)) {\n\n\t\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t}\n\t\t\t/* we add a socket to the multihomed socket */\n\t\t\tsockPtr->count++;\n\t\t}\n\t}\n\n\t/* get_ifi_info returned an error */\n\tif (ifihead == NULL) {\n\n\t\tCWDeleteList(&interfaceList, CWNetworkDeleteMHInterface);\n\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"Error With get_ifi_info()\");\n\t}\n\tfree_ifi_info(ifihead);\n\n#ifdef IPV6\n\t/* we are an IPv6 server */\n\tif (gNetworkPreferredFamily == CW_IPv6) {\n\t\t/*\n\t\t * Store IPv4 addresses for our interfaces in the field \"addrIPv4\".\n\t\t * Consider aliases as different interfaces (last arg of get_ifi_info is 1).\n\t\t * Why? Just to increase the funny side of the thing.\n\t\t */\n#ifdef CW_DEBUGGING\n\t\tfor (ifihead = ifi = get_ifi_info(AF_INET, 1); ifi != NULL; ifi = ifi->ifi_next) {\n#else\n\t\tfor (ifihead = ifi = get_ifi_info(AF_INET, 0); ifi != NULL; ifi = ifi->ifi_next) {\n#endif\n\t\t\tCWMultiHomedInterface *s = CWNetworkGetInterfaceAlreadyStored(interfaceList, ifi->ifi_index);\n\n\t\t\tif (s == NULL ||\n\t\t\t    s->kind != CW_PRIMARY ||\n\t\t\t    s->addrIPv4.ss_family != AF_UNSPEC || ifi->ifi_addr->sa_family != AF_INET)\n\t\t\t\tcontinue;\n\n\t\t\tCW_COPY_NET_ADDR_PTR(&(s->addrIPv4), ifi->ifi_addr);\n\n\t\t\tCWUseSockNtop(&(s->addrIPv4),\n\t\t\t\t      CWDebugLog(\"IPv4 address %s (%d, %s)\", str, ifi->ifi_index, ifi->ifi_name);\n\t\t\t    );\n\t\t}\n\t\t/* get_ifi_info returned an error */\n\t\tif (ifihead == NULL) {\n\n\t\t\tCWDeleteList(&interfaceList, CWNetworkDeleteMHInterface);\n\t\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"Error with get_ifi_info()\");\n\t\t}\n\t\tfree_ifi_info(ifihead);\n\t}\n#endif\n\t/* bind wildcard address */\n#ifdef  IPV6\n\tif (gNetworkPreferredFamily == CW_IPv6) {\n\n\t\tif ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {\n\t\t\tgoto fail;\n\t\t}\n\t} else\n#endif\n\t{\n\t\tif ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)\n\t\t\tgoto fail;\n\t}\n\n\tgoto success;\n\n fail:\n\tCWDeleteList(&interfaceList, CWNetworkDeleteMHInterface);\n\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\t/* this wil return */\n\t/* not reached */\n\n success:\n\t/* reuse address */\n\tsetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));\n\tCW_ZERO_MEMORY(&wildaddr, sizeof(wildaddr));\n\n#ifdef  IPV6\n\tif (gNetworkPreferredFamily == CW_IPv6) {\n\t\t/* fill wildaddr considering it an IPv6 addr */\n\t\tstruct sockaddr_in6 *a = (struct sockaddr_in6 *)&wildaddr;\n\t\ta->sin6_family = AF_INET6;\n\t\ta->sin6_addr = in6addr_any;\n\t\ta->sin6_port = htons(port);\n\t} else\n#endif\n\t{\n\t\t/* fill wildaddr considering it an IPv4 addr */\n\t\tstruct sockaddr_in *a = (struct sockaddr_in *)&wildaddr;\n\t\ta->sin_family = AF_INET;\n\t\ta->sin_addr.s_addr = htonl(INADDR_ANY);\n\t\ta->sin_port = htons(port);\n\t}\n\n\tif (bind(sock, (struct sockaddr *)&wildaddr, CWNetworkGetAddressSize(&wildaddr)) < 0) {\n\t\tclose(sock);\n\t\tCWDeleteList(&interfaceList, CWNetworkDeleteMHInterface);\n\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tCWUseSockNtop(&wildaddr, CWLog(\"bound %s\", str););\n\n\tCW_CREATE_OBJECT_ERR(p, CWMultiHomedInterface, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tp->sock = sock;\n\tp->kind = CW_BROADCAST_OR_ALIAS;\n\tp->systemIndex = -1;\t/* make sure this can't be\n\t\t\t\t   confused with an interface */\n\n\t/* addrIPv4 field for the wildcard address cause it\n\t * is garbage in both cases (IPv4 + IPv6)\n\t */\n\tp->addrIPv4.ss_family = AF_UNSPEC;\n\n\tCW_COPY_NET_ADDR_PTR(&(p->addr), &wildaddr);\n\tif (!CWAddElementToList(&interfaceList, p)) {\n\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t}\n\tsockPtr->count++;\n\n\t/* bind multicast addresses */\n\tfor (i = 0; i < multicastGroupsCount; i++) {\n\t\tstruct addrinfo hints, *res, *ressave;\n\t\tchar serviceName[5];\n\t\tCWSocket sock;\n\n\t\tCW_ZERO_MEMORY(&hints, sizeof(struct addrinfo));\n\t\thints.ai_family = AF_UNSPEC;\n\t\thints.ai_socktype = SOCK_DGRAM;\n\n\t\t/* endianness will be handled by getaddrinfo */\n\t\tsnprintf(serviceName, 5, \"%d\", CW_CONTROL_PORT);\n\n\t\tCWLog(\"Joining Multicast Group: %s...\", multicastGroups[i]);\n\n\t\tif (getaddrinfo(multicastGroups[i], serviceName, &hints, &res) != 0) {\n\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t}\n\t\tressave = res;\n\n\t\tdo {\n\t\t\tif ((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {\n\t\t\t\tcontinue;\t/* try next address */\n\t\t\t}\n\n\t\t\t/* reuse address */\n\t\t\tsetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));\n\n\t\t\tif (bind(sock, res->ai_addr, res->ai_addrlen) == 0)\n\t\t\t\tbreak;\t/* success */\n\n\t\t\tclose(sock);\t/* failure */\n\t\t} while ((res = res->ai_next) != NULL);\n\n\t\tif (res == NULL) {\t/* error on last iteration */\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t}\n\n\t\tif (mcast_join(sock, res->ai_addr, res->ai_addrlen, NULL, 0) != 0) {\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t}\n\n\t\tCWUseSockNtop((res->ai_addr), CWLog(\"Joined Multicast Group: %s\", str););\n\n\t\tCW_CREATE_OBJECT_ERR(p, CWMultiHomedInterface, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tp->sock = sock;\n\t\tp->kind = CW_BROADCAST_OR_ALIAS;\n\t\tp->systemIndex = -1;\n\n\t\tp->addrIPv4.ss_family = AF_UNSPEC;\n\n\t\tCW_COPY_NET_ADDR_PTR(&(p->addr), res->ai_addr);\n\t\tif (!CWAddElementToList(&interfaceList, p)) {\n\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t}\n\t\tsockPtr->count++;\t/* we add a socket to the multihomed socket */\n\n\t\tfreeaddrinfo(ressave);\n\t}\n\n\t/*\n\t * Lists are fun when you don't know how many sockets will not give an\n\t * error on creating/binding, but now that we know the exact number we\n\t * convert it into an array. The \"interfaces\" field of CWMultiHomedSocket\n\t * is actually an array.\n\t */\n\tCW_CREATE_ARRAY_ERR((sockPtr->interfaces), sockPtr->count, CWMultiHomedInterface,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/* create array from list */\n\tfor (el = interfaceList, i = 0; el != NULL; el = el->next, i++) {\n\t\tCW_COPY_MH_INTERFACE_PTR(&((sockPtr->interfaces)[i]), ((CWMultiHomedInterface *) (el->data)));\n\t}\n\n\t/* delete the list */\n\tCWDeleteList(&interfaceList, CWNetworkDeleteMHInterface);\n\n\treturn CW_TRUE;\n}\n\nvoid CWNetworkCloseMultiHomedSocket(CWMultiHomedSocket * sockPtr)\n{\n\n\tint i = 0;\n\n\tif (sockPtr == NULL || sockPtr->interfaces == NULL)\n\t\treturn;\n\n\tfor (i = 0; i < sockPtr->count; i++)\n\t\tclose(sockPtr->interfaces[i].sock);\n\n\tCW_FREE_OBJECT(sockPtr->interfaces);\n\tsockPtr->count = 0;\n}\n\nint get_mac_addr(unsigned char *outBuf, char *eth_name)\n{\n\n\tstruct ifreq s;\n\tint fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);\n\tstrcpy(s.ifr_name, eth_name);\n\tif (!ioctl(fd, SIOCGIFHWADDR, &s))\n\t\tmemcpy(outBuf, s.ifr_addr.sa_data, 6);\n\n\treturn 0;\n}\n\n/*\n * Blocks until one ore more interfaces are ready to read something. When there\n * is at least one packet pending, call CWManageIncomingPacket() for each pending\n * packet, then return.\n */\nCWBool CWNetworkUnsafeMultiHomed(CWMultiHomedSocket * sockPtr,\n\t\t\t\t void (*CWManageIncomingPacket) (CWSocket,\n\t\t\t\t\t\t\t\t unsigned char *,\n\t\t\t\t\t\t\t\t int,\n\t\t\t\t\t\t\t\t int, CWNetworkLev4Address *, CWBool), CWBool peekRead)\n{\n\tfd_set fset;\n\tint max = 0, i;\n\tCWNetworkLev4Address addr;\n\tCWNetworkLev4Address address;\n\n\tint k;\n\tint fragmentsNum = 0;\n\tCWProtocolMessage *completeMsgPtr = NULL;\n\tCWProtocolMessage *frame = NULL;\n\tint dataSocket = 0;\n\tint readBytes;\n\tint flags = ((peekRead != CW_FALSE) ? MSG_PEEK : 0);\n\tunsigned char buf[CW_BUFFER_SIZE];\n\n\tif (sockPtr == NULL || sockPtr->count == 0 || CWManageIncomingPacket == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tFD_ZERO(&fset);\n\n\t/* select() on all the sockets */\n\tfor (i = 0; i < sockPtr->count; i++) {\n\n\t\tFD_SET(sockPtr->interfaces[i].sock, &fset);\n\n\t\tif (sockPtr->interfaces[i].sock > max)\n\t\t\tmax = sockPtr->interfaces[i].sock;\n\n\t\tif (sockPtr->interfaces[i].dataSock != 0) {\t// Todd: add tap device to 'select '\n\t\t\tFD_SET(sockPtr->interfaces[i].dataSock, &fset);\n\n\t\t\tif (sockPtr->interfaces[i].dataSock > max)\n\t\t\t\tmax = sockPtr->interfaces[i].dataSock;\n\t\t}\n\t}\n\n\tfor (i = 0; i < gMaxWTPs; i++) {\n\t\tif (gWTPs[i].tap_fd != 0) {\n\t\t\tFD_SET(gWTPs[i].tap_fd, &fset);\n\n\t\t\tif (gWTPs[i].tap_fd > max)\n\t\t\t\tmax = gWTPs[i].tap_fd;\n\t\t}\n\t}\n\n\twhile (select(max + 1, &fset, NULL, NULL, NULL) < 0) {\n\n\t\tif (errno != EINTR) {\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_GENERAL);\n\t\t}\n\t}\n\n\t/* calls CWManageIncomingPacket() for each interface\n\t * that has an incoming packet\n\t */\n\n\tfor (i = 0; i < gMaxWTPs; i++) {\n\t\t// CWDebugLog(\"Parsing TAP %d\", gWTPs[i].tap_fd);\n\n\t\tif (FD_ISSET(gWTPs[i].tap_fd, &fset)) {\n\n\t\t\treadBytes = read(gWTPs[i].tap_fd, buf, CW_BUFFER_SIZE);\t//Todd: read from TAP then forward to WTP through data channel\n\t\t\tCWDebugLog(\"gWTPs[%d].tap_fd:%d is set,data(%d bytes)\", i, gWTPs[i].tap_fd, readBytes);\n\n\t\t\tif (readBytes < 0) {\n\t\t\t\tCWDebugLog(\"Reading from tap interface\");\n\t\t\t\tperror(\"Reading from interface\");\n\t\t\t\tclose(gWTPs[i].tap_fd);\n\t\t\t\tgWTPs[i].tap_fd = 0;\n\t\t\t}\n\n\t\t\tif (gWTPs[i].currentState != CW_ENTER_RUN) {\n\t\t\t\tCWDebugLog(\"WTP %d is not in RUN State. The packet was dropped.\", i);\n\t\t\t\tcontinue;\n\t\t\t} else {\n\n\t\t\t\tunsigned char macAddrTap[6];\n\t\t\t\tget_mac_addr(macAddrTap, gWTPs[i].tap_name);\n\t\t\t\tunsigned char buf80211[CW_BUFFER_SIZE + 24];\n\t\t\t\tint readByest80211 = from_8023_to_80211(buf, readBytes, buf80211, macAddrTap);\n\t\t\t\tCW_CREATE_OBJECT_ERR(frame, CWProtocolMessage, return 0;\n\t\t\t\t    );\n\t\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*frame, readByest80211, return 0;\n\t\t\t\t    );\n\t\t\t\tmemcpy(frame->msg, buf80211, readByest80211);\n\t\t\t\tframe->offset = readByest80211;\n\t\t\t\tframe->data_msgType = CW_IEEE_802_11_FRAME_TYPE;\n\n\t\t\t\tif (!CWAssembleDataMessage(&completeMsgPtr,\n\t\t\t\t\t\t\t   &fragmentsNum,\n\t\t\t\t\t\t\t   gWTPs[i].pathMTU, frame, NULL, CW_PACKET_PLAIN, 0)) {\n\n\t\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t\t\t}\n\t\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*frame);\n\t\t\t\t\tCW_FREE_OBJECT(frame);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfor (k = 0; k < sockPtr->count; k++) {\n\t\t\t\t\tif (sockPtr->interfaces[k].sock == gWTPs[i].socket) {\n\t\t\t\t\t\tdataSocket = sockPtr->interfaces[k].dataSock;\n\t\t\t\t\t\tCW_COPY_NET_ADDR_PTR(&address, &(gWTPs[i].dataAddress));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (dataSocket == 0) {\n\t\t\t\t\tCWDebugLog(\"data socket of WTP %d isn't ready.\");\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t/* Set port and address of data tunnel */\n\t\t\t\t//sock_set_port_cw((struct sockaddr *)&(address), htons(CW_DATA_PORT));\n\n\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\tif (!CWNetworkSendUnsafeUnconnected(dataSocket,\n\t\t\t\t\t\t\t\t\t    &(address),\n\t\t\t\t\t\t\t\t\t    completeMsgPtr[k].msg,\n\t\t\t\t\t\t\t\t\t    completeMsgPtr[k].offset)) {\n\t\t\t\t\t\tCWDebugLog(\"Failure sending Request\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t\t}\n\n\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*(frame));\n\t\t\t\tCW_FREE_OBJECT(frame);\n\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i = 0; i < sockPtr->count; i++) {\n\n\t\tif (FD_ISSET(sockPtr->interfaces[i].sock, &fset)) {\n\t\t\tint readBytes;\n\n\t\t\t/*\n\t\t\t   CWUseSockNtop(&(sockPtr->interfaces[i].addr),\n\t\t\t   CWDebugLog(\"Ready on %s\", str);\n\t\t\t   );\n\t\t\t */\n\n\t\t\tCW_ZERO_MEMORY(buf, CW_BUFFER_SIZE);\n\n\t\t\t/* message */\n\t\t\tif (!CWErr\n\t\t\t    (CWNetworkReceiveUnsafe\n\t\t\t     (sockPtr->interfaces[i].sock, buf, CW_BUFFER_SIZE - 1, flags, &addr, &readBytes))) {\n\n\t\t\t\tsleep(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tCWManageIncomingPacket(sockPtr->interfaces[i].sock,\n\t\t\t\t\t       buf,\n\t\t\t\t\t       readBytes,\n\t\t\t\t\t       CWNetworkGetInterfaceIndexFromSystemIndex(sockPtr,\n\t\t\t\t\t\t\t\t\t\t\t sockPtr->interfaces[i].\n\t\t\t\t\t\t\t\t\t\t\t systemIndex), &addr, CW_FALSE);\n\t\t}\n\n\t\tif (FD_ISSET(sockPtr->interfaces[i].dataSock, &fset)) {\t//Todd: Bridge 802.3 packets of WTPs into AC\n\t\t\tint readBytes;\n\n\t\t\tCW_ZERO_MEMORY(buf, CW_BUFFER_SIZE);\n\n\t\t\t/* message */\n\t\t\tif (!CWErr\n\t\t\t    (CWNetworkReceiveUnsafe\n\t\t\t     (sockPtr->interfaces[i].dataSock, buf, CW_BUFFER_SIZE - 1, flags, &addr, &readBytes))) {\n\n\t\t\t\tsleep(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tCWManageIncomingPacket(sockPtr->interfaces[i].dataSock,\n\t\t\t\t\t       buf,\n\t\t\t\t\t       readBytes,\n\t\t\t\t\t       CWNetworkGetInterfaceIndexFromSystemIndex(sockPtr,\n\t\t\t\t\t\t\t\t\t\t\t sockPtr->interfaces[i].\n\t\t\t\t\t\t\t\t\t\t\t systemIndex), &addr, CW_TRUE);\n\t\t}\n\t\t/* else {CWDebugLog(\"~~~~~~~Non Ready on....~~~~~~\");} */\n\t}\n\treturn CW_TRUE;\n}\n\n/* count distinct interfaces managed by the multihomed socket */\nint CWNetworkCountInterfaceAddresses(CWMultiHomedSocket * sockPtr)\n{\n\n\tint count = 0;\n\tint i;\n\n\tif (sockPtr == NULL)\n\t\treturn 0;\n\n\tfor (i = 0; i < sockPtr->count; i++) {\n\n\t\tif (sockPtr->interfaces[i].kind == CW_PRIMARY)\n\t\t\tcount++;\n\t}\n\n\treturn count;\n}\n\n/*\n * Get the addresses of each distinct interface managed by the multihomed\n * socket. If we are an IPv6 server element with index i of addressesPtr contains\n * the IPv6 address of the interface at index i (our mapped index, not system\n * index) and the element at index i of IPv4AddressesPtr contains the IPv4\n * equivalent address for the interface at index i. If we are an IPv4 server,\n * addressesPtr are the IPv4 addresses and IPv4AddressesPtr is garbage.\n */\nCWBool CWNetworkGetInterfaceAddresses(CWMultiHomedSocket * sockPtr,\n\t\t\t\t      CWNetworkLev4Address ** addressesPtr, struct sockaddr_in ** IPv4AddressesPtr)\n{\n\tint i, j;\n\n\tif (sockPtr == NULL || addressesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_ARRAY_ERR(*addressesPtr,\n\t\t\t    CWNetworkCountInterfaceAddresses(sockPtr),\n\t\t\t    CWNetworkLev4Address, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (IPv4AddressesPtr != NULL && gNetworkPreferredFamily == CW_IPv6) {\n\n\t\tCW_CREATE_ARRAY_ERR(*IPv4AddressesPtr,\n\t\t\t\t    CWNetworkCountInterfaceAddresses(sockPtr),\n\t\t\t\t    struct sockaddr_in, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\n\tfor (i = 0, j = 0; i < sockPtr->count; i++) {\n\n\t\tif (sockPtr->interfaces[i].kind == CW_PRIMARY) {\n\n\t\t\tCW_COPY_NET_ADDR_PTR(&((*addressesPtr)[j]),\n\t\t\t\t\t     ((CWNetworkLev4Address *) & (sockPtr->interfaces[i].addr)));\n\n\t\t\tif (IPv4AddressesPtr != NULL && gNetworkPreferredFamily == CW_IPv6) {\n\n\t\t\t\tCW_COPY_NET_ADDR_PTR(&((*IPv4AddressesPtr)[j]),\n\t\t\t\t\t\t     ((CWNetworkLev4Address *) & (sockPtr->interfaces[i].addrIPv4)));\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t}\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACMultiHomedSocket.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWMultiHomedSocket_HEADER__\n#define __CAPWAP_CWMultiHomedSocket_HEADER__\n\n#include \"CWNetwork.h\"\n\n/*_____________________________________________________*/\n/*  *******************___TYPES___*******************  */\n\ntypedef struct {\n\tCWNetworkLev4Address addr;\n\tCWNetworkLev4Address addrIPv4;\n\tCWSocket sock;\n\tenum {\n\t\tCW_PRIMARY,\n\t\tCW_BROADCAST_OR_ALIAS\n\t} kind;\n\tshort systemIndex;\t// real interface index in the system\n\n\tCWNetworkLev4Address dataAddr;\n\tCWSocket dataSock;\n} CWMultiHomedInterface;\n\ntypedef struct {\n\tint count;\n\tCWMultiHomedInterface *interfaces;\n} CWMultiHomedSocket;\n\n/*_____________________________________________________*/\n/*  *******************___MACRO___*******************  */\n\n#define CW_COPY_MH_INTERFACE_PTR(int1, int2)        CW_COPY_NET_ADDR_PTR( &((int1)->addr), &((int2)->addr));    \\\n                            CW_COPY_NET_ADDR_PTR( &((int1)->addrIPv4), &((int2)->addrIPv4));\\\n                            (int1)->sock = (int2)->sock;                    \\\n                            (int1)->dataSock = (int2)->dataSock;                \\\n                            (int1)->kind = (int2)->kind;    \\\n                            (int1)->systemIndex = (int2)->systemIndex;\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\n\nCWBool CWNetworkInitSocketServerMultiHomed(CWMultiHomedSocket * sockPtr, int port, char **multicastGroups,\n\t\t\t\t\t   int multicastGroupsCount);\nvoid CWNetworkCloseMultiHomedSocket(CWMultiHomedSocket * sockPtr);\nCWBool CWNetworkUnsafeMultiHomed(CWMultiHomedSocket * sockPtr,\n\t\t\t\t void (*CWManageIncomingPacket) (CWSocket, unsigned char *, int, int, CWNetworkLev4Address *,\n\t\t\t\t\t\t\t\t CWBool), CWBool peekRead);\nint CWNetworkCountInterfaceAddresses(CWMultiHomedSocket * sockPtr);\nCWBool CWNetworkGetInterfaceAddresses(CWMultiHomedSocket * sockPtr, CWNetworkLev4Address ** addressesPtr,\n\t\t\t\t      struct sockaddr_in **IPv4AddressesPtr);\n\n#endif\n"
  },
  {
    "path": "ACProtocol.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n#include \"CWVendorPayloads.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\nunsigned char WTPRadioInformationType;\n\n/*____________________________________________________________________________*/\n/*  *****************************___ASSEMBLE___*****************************  */\n/*Update 2009:\n    Assemble protocol Configuration update request.\n    Mainly added to  manage vendor specific packets*/\nCWBool CWProtocolAssembleConfigurationUpdateRequest(CWProtocolMessage ** msgElems, int *msgElemCountPtr,\n\t\t\t\t\t\t    int MsgElementType)\n{\n\tint *iPtr;\n\tint k = -1;\n\n\tif (msgElems == NULL || msgElemCountPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\n\t*msgElemCountPtr = 1;\n\n\tCWLog(\"Assembling Protocol Configuration Update Request...\");\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(*msgElems, *msgElemCountPtr, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/* Selection of type of Conf Update Request */\n\n\tswitch (MsgElementType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\n\t\t// Assemble Message Elements\n\t\tif (!(CWAssembleWTPVendorPayloadUCI(&(*msgElems[++k])))) {\n\t\t\tint i;\n\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*msgElems[i]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(*msgElems);\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\t\tbreak;\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\n\t\t// Assemble Message Elements\n\t\tif (!(CWAssembleWTPVendorPayloadWUM(&(*msgElems[++k])))) {\n\t\t\tint i;\n\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*msgElems[i]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(*msgElems);\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\t\tbreak;\n\tdefault:{\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\t}\n\n\tCWLog(\"Protocol Configuration Update Request Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemACWTPRadioInformation(CWProtocolMessage * msgPtr)\n{\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);;\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 5, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, 0);\t// Radio ID\n\tCWProtocolStore8(msgPtr, 0);\t// Reserved\n\tCWProtocolStore8(msgPtr, 0);\t// Reserved\n\tCWProtocolStore8(msgPtr, 0);\t// Reserved\n\tCWProtocolStore8(msgPtr, 0);\t// Radio Information Type ABGN\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemACDescriptor(CWProtocolMessage * msgPtr)\n{\n\tCWACVendorInfos infos;\n\tint i = 0, size = 0;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);;\n\n\tif (!CWACGetVendorInfos(&infos)) {\t// get infos\n\t\treturn CW_FALSE;\n\t}\n\n\tfor (i = 0; i < infos.vendorInfosCount; i++) {\n\t\tsize += (8 + ((infos.vendorInfos)[i]).length);\n\t}\n\n\tsize += 12;\t\t// size of message in bytes (excluding vendor infos, already counted)\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, size, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore16(msgPtr, CWACGetStations());\t// Number of mobile stations associated\n\tCWProtocolStore16(msgPtr, CWACGetLimit());\t// Maximum number of mobile stations supported\n\tCWProtocolStore16(msgPtr, CWACGetActiveWTPs());\t// Number of WTPs active\n\tCWProtocolStore16(msgPtr, CWACGetMaxWTPs());\t// Maximum number of WTPs supported\n\tCWProtocolStore8(msgPtr, CWACGetSecurity());\n\tCWProtocolStore8(msgPtr, CWACGetRMACField());\n\tCWProtocolStore8(msgPtr, 0);\t//Reserved\n\tCWProtocolStore8(msgPtr, CWACGetDTLSPolicy());\t// DTLS Policy\n\n\tfor (i = 0; i < infos.vendorInfosCount; i++) {\n\t\tCWProtocolStore32(msgPtr, ((infos.vendorInfos)[i].vendorIdentifier));\n\t\tCWProtocolStore16(msgPtr, ((infos.vendorInfos)[i].type));\n\t\tCWProtocolStore16(msgPtr, ((infos.vendorInfos)[i].length));\n\t\tif ((infos.vendorInfos)[i].length == 4) {\n\t\t\t*((infos.vendorInfos)[i].valuePtr) = htonl(*((infos.vendorInfos)[i].valuePtr));\n\t\t}\n\t\tCWProtocolStoreRawBytes(msgPtr, (unsigned char*)((infos.vendorInfos)[i].valuePtr),\n\t\t\t\t\t(infos.vendorInfos)[i].length);\n\t}\n\n\tCWACDestroyVendorInfos(&infos);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_AC_DESCRIPTOR_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemACIPv4List(CWProtocolMessage * msgPtr)\n{\n\tint *list;\n\tint count, i;\n\tconst int IPv4_List_length = 4;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!CWACGetACIPv4List(&list, &count))\n\t\treturn CW_FALSE;\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, IPv4_List_length * count, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < count; i++) {\n\t\tCWProtocolStore32(msgPtr, list[i]);\n//      CWDebugLog(\"AC IPv4 List(%d): %d\", i, list[i]);\n\t}\n\n\tCW_FREE_OBJECT(list);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_AC_IPV4_LIST_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemACIPv6List(CWProtocolMessage * msgPtr)\n{\n\tstruct in6_addr *list;\n\tconst int IPv6_List_length = 16;\n\tint count, i;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!CWACGetACIPv6List(&list, &count))\n\t\treturn CW_FALSE;\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, IPv6_List_length * count, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/*--- ATTENZIONE! l'indirizzo ipv6 forse deve essere girato ---*/\n\tfor (i = 0; i < count; i++) {\n\t\tCWProtocolStoreRawBytes(msgPtr, list[i].s6_addr, 16);\n\t}\n\n\tCW_FREE_OBJECT(list);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_AC_IPV6_LIST_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemACName(CWProtocolMessage * msgPtr)\n{\n\tchar *name;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tname = CWACGetName();\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, strlen(name), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStoreStr(msgPtr, name);\n\n//  CWDebugLog(\"AC Name: %s\", name);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_AC_NAME_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemAddWLAN(int radioID, CWProtocolMessage * msgPtr, unsigned char *recv_packet, int len_packet)\n{\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len_packet, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStoreRawBytes(msgPtr, recv_packet, len_packet);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_IEEE80211_ADD_WLAN_CW_TYPE);\n\n}\n\nCWBool CWAssembleMsgElemDeleteWLAN(int radioID, CWProtocolMessage * msgPtr, unsigned char *recv_packet, int len_packet)\n{\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len_packet, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStoreRawBytes(msgPtr, recv_packet, len_packet);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_IEEE80211_DELETE_WLAN_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemAddStation(int radioID, CWProtocolMessage * msgPtr, unsigned char *StationMacAddr)\n{\n\tconst int add_Station_Length = 8;\n\tint Length = 6;\t\t//mac address length in bytes (48 bit)\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, add_Station_Length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, radioID);\n\n\tCWProtocolStore8(msgPtr, Length);\n\n\tCWProtocolStoreRawBytes(msgPtr, StationMacAddr, Length);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_ADD_STATION_CW_TYPE);\n\n}\n\nCWBool CWAssembleMsgElemDeleteStation(int radioID, CWProtocolMessage * msgPtr, unsigned char *StationMacAddr)\n{\n\tconst int delete_Station_Length = 8;\n\tint Length = 6;\t\t//mac address length in bytes (48 bit)\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, delete_Station_Length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tCWProtocolStore8(msgPtr, radioID);\n\tCWProtocolStore8(msgPtr, Length);\n\tCWProtocolStoreRawBytes(msgPtr, StationMacAddr, Length);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_DELETE_STATION_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemCWControlIPv4Addresses(CWProtocolMessage * msgPtr)\n{\n\tint count, i;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tcount = CWACGetInterfacesCount();\n\n\tif (count <= 0) {\n\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"No Interfaces Configured\");\n\t}\n\n\tfor (i = 0; i < count; i++) {\t// one Message Element for each interface\n\t\tCWProtocolMessage temp;\n\t\t// create message\n\t\tCW_CREATE_PROTOCOL_MESSAGE(temp, 6, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tCWProtocolStore32(&temp, CWACGetInterfaceIPv4AddressAtIndex(i));\n\t\tCWProtocolStore16(&temp, CWACGetInterfaceWTPCountAtIndex(i));\n\n\t\tCWAssembleMsgElem(&temp, CW_MSG_ELEMENT_CW_CONTROL_IPV4_ADDRESS_CW_TYPE);\n\n\t\tif (i == 0) {\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, (temp.offset) * count,\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t}\n\n\t\tCWProtocolStoreMessage(msgPtr, &temp);\n\t\tCW_FREE_PROTOCOL_MESSAGE(temp);\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemCWControlIPv6Addresses(CWProtocolMessage * msgPtr)\n{\n\tint count, i;\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tcount = CWACGetInterfacesCount();\n\n\tfor (i = 0; i < count; i++) {\t// one Message Element for each interface\n\t\tCWProtocolMessage temp;\n\t\t// create message\n\t\tCW_CREATE_PROTOCOL_MESSAGE(temp, 18, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tCWProtocolStoreRawBytes(&temp, CWACGetInterfaceIPv6AddressAtIndex(i), 16);\n\t\tCWProtocolStore16(&temp, CWACGetInterfaceWTPCountAtIndex(i));\n\n\t\tCWAssembleMsgElem(&temp, CW_MSG_ELEMENT_CW_CONTROL_IPV6_ADDRESS_CW_TYPE);\n\n\t\tif (i == 0) {\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, (temp.offset) * count,\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t}\n\n\t\tCWProtocolStoreMessage(msgPtr, &temp);\n\t\tCW_FREE_PROTOCOL_MESSAGE(temp);\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemCWTimer(CWProtocolMessage * msgPtr)\n{\n\tint discoveryTimer, echoTimer;\n\tconst int CWTimer_length = 2;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, CWTimer_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!(CWACGetDiscoveryTimer(&discoveryTimer)) || !(CWACGetEchoRequestTimer(&echoTimer)))\n\t\treturn CW_FALSE;\n\tCWProtocolStore8(msgPtr, discoveryTimer);\n\tCWProtocolStore8(msgPtr, echoTimer);\n\n//  CWDebugLog(\"Discovery Timer: %d\", discoveryTimer);\n//  CWDebugLog(\"Echo Timer: %d\", echoTimer);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_CW_TIMERS_CW_TYPE);\n}\n\n/* Le informazioni sui Radio ID vengono prese dalle informazioni del Configure Message\n   Provvisoriamente l'error Report Period è settato allo stesso valore per tutte le radio del WTP*/\nCWBool CWAssembleMsgElemDecryptErrorReportPeriod(CWProtocolMessage * msgPtr)\n{\n\tconst int radio_Decrypt_Error_Report_Period_Length = 3;\n\tconst int reportInterval = 15;\n\tCWProtocolMessage *msgs;\n\tCWRadioAdminInfoValues *radiosInfoPtr;\n\tint radioCount = 0;\n\tint *iPtr;\n\tint len = 0;\n\tint i;\n\tint j;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\tCWLog(\"Critical Error... closing thread\");\n\t\tCWCloseThread();\n\t}\n\n\tradiosInfoPtr = gWTPs[*iPtr].WTPProtocolManager.radioAdminInfo.radios;\n\tradioCount = gWTPs[*iPtr].WTPProtocolManager.radioAdminInfo.radiosCount;\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgs, radioCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < radioCount; i++) {\n\t\t// create message\n\t\tCW_CREATE_PROTOCOL_MESSAGE(msgs[i], radio_Decrypt_Error_Report_Period_Length,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tCWProtocolStore8(&(msgs[i]), radiosInfoPtr[i].ID);\t// ID of the radio\n\t\tCWProtocolStore16(&(msgs[i]), reportInterval);\t// state of the radio\n\n\t\tif (!(CWAssembleMsgElem(&(msgs[i]), CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_PERIOD_CW_TYPE))) {\n\t\t\tfor (j = i; j >= 0; j--) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[j]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(msgs);\n\t\t\treturn CW_FALSE;\n\t\t}\n\n\t\tlen += msgs[i].offset;\n//      CWDebugLog(\"Decrypt Error Report Period: %d - %d\", radiosInfoPtr[i].ID, reportInterval);\n\t}\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < radioCount; i++) {\n\t\tCWProtocolStoreMessage(msgPtr, &(msgs[i]));\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[i]);\n\t}\n\n\tCW_FREE_OBJECT(msgs);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemIdleTimeout(CWProtocolMessage * msgPtr)\n{\n\tint idleTimeout;\n\tconst int idle_Timeout_length = 4;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, idle_Timeout_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!(CWACGetIdleTimeout(&idleTimeout)))\n\t\treturn CW_FALSE;\n\tCWProtocolStore32(msgPtr, idleTimeout);\n\n//  CWDebugLog(\"Idle Timeout: %d\", idleTimeout);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_IDLE_TIMEOUT_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPFallback(CWProtocolMessage * msgPtr)\n{\n\tint value = 0;\t\t//PROVVISORIO\n\tconst int WTP_fallback_length = 1;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, WTP_fallback_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, value);\n\n//  CWDebugLog(\"Fallback: %d\", value);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_FALLBACK_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemRadioOperationalState(int radioID, CWProtocolMessage * msgPtr)\n{\n\tconst int radio_Operational_State_Length = 3;\n\tCWRadiosOperationalInfo infos;\n\tCWProtocolMessage *msgs;\n\tint len = 0;\n\tint i;\n\tint j;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!(CWGetWTPRadiosOperationalState(radioID, &infos))) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgs, (infos.radiosCount), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\t// create message\n\t\tCW_CREATE_PROTOCOL_MESSAGE(msgs[i], radio_Operational_State_Length,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].ID);\t// ID of the radio\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].state);\t// state of the radio\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].cause);\n\n\t\tif (!(CWAssembleMsgElem(&(msgs[i]), CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE))) {\n\t\t\tfor (j = i; j >= 0; j--) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[j]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(infos.radios);\n\t\t\tCW_FREE_OBJECT(msgs);\n\t\t\treturn CW_FALSE;\n\t\t}\n\n\t\tlen += msgs[i].offset;\n//      CWDebugLog(\"Radio operational State: %d - %d - %d\", infos.radios[i].ID, infos.radios[i].state, infos.radios[i].cause);\n\t}\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\tCWProtocolStoreMessage(msgPtr, &(msgs[i]));\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[i]);\n\t}\n\n\tCW_FREE_OBJECT(msgs);\n\tCW_FREE_OBJECT(infos.radios);\n\n\treturn CW_TRUE;\n}\n\n/*_________________________________________________________________________*/\n/*  *****************************___PARSE___*****************************  */\nCWBool CWParseACNameWithIndex(CWProtocolMessage * msgPtr, int len, CWACNameWithIndexValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->index = CWProtocolRetrieve8(msgPtr);\n\t//CWDebugLog(\"CW_MSG_ELEMENT_WTP_RADIO_ID: %d\", (valPtr->radios)[radioIndex].ID);\n\n\tvalPtr->ACName = CWProtocolRetrieveStr(msgPtr, len - 1);\n\t//CWDebugLog(\"CW_MSG_ELEMENT_WTP_RADIO_TYPE: %d\",   (valPtr->radios)[radioIndex].type);\n\n\t//CWDebugLog(\"AC Name with index: %d - %s\", valPtr->index, valPtr->ACName);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseDiscoveryType(CWProtocolMessage * msgPtr, int len, CWDiscoveryRequestValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->type = CWProtocolRetrieve8(msgPtr);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseLocationData(CWProtocolMessage * msgPtr, int len, char **valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*valPtr = CWProtocolRetrieveStr(msgPtr, len);\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n//  CWDebugLog(\"Location Data:%s\", *valPtr);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseMsgElemDuplicateIPv4Address(CWProtocolMessage * msgPtr, int len, WTPDuplicateIPv4 * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->ipv4Address = CWProtocolRetrieve32(msgPtr);\n\tvalPtr->status = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->length = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->MACoffendingDevice_forIpv4 = (unsigned char *)CWProtocolRetrieveRawBytes(msgPtr, valPtr->length);\n\n\t//valPtr->MACoffendingDevice_forIpv4 = (unsigned char*)CWProtocolRetrieveRawBytes(msgPtr,6);\n\t//valPtr->status = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"Duplicate IPv4: %d\", valPtr->ipv4Address);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseMsgElemDuplicateIPv6Address(CWProtocolMessage * msgPtr, int len, WTPDuplicateIPv6 * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tint i;\n\tfor (i = 0; i < 16; i++) {\n\t\tunsigned char *aux;\n\t\taux = CWProtocolRetrieveRawBytes(msgPtr, 1);\n\t\t(valPtr->ipv6Address).s6_addr[i] = *aux;\n\t}\n\n//  CWDebugLog(\"Duplicate IPv6\");\n\t//valPtr->MACoffendingDevice_forIpv6 = (unsigned char*)CWProtocolRetrieveRawBytes(msgPtr,6);\n\n\tvalPtr->status = CWProtocolRetrieve8(msgPtr);\n\n\tvalPtr->length = CWProtocolRetrieve8(msgPtr);\n\n\tvalPtr->MACoffendingDevice_forIpv6 = (unsigned char *)CWProtocolRetrieveRawBytes(msgPtr, valPtr->length);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPStatisticsTimer(CWProtocolMessage * msgPtr, int len, int *valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*valPtr = CWProtocolRetrieve16(msgPtr);\n\n//  CWDebugLog(\"WTP Statistics Timer: %d\", *valPtr);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPBoardData(CWProtocolMessage * msgPtr, int len, CWWTPVendorInfos * valPtr)\n{\n\tint theOffset, i, vendorID;\n\tCWParseMessageElementStart();\n\n\tvalPtr->vendorInfosCount = 0;\n\n\t// see how many vendor ID we have in the message\n\tvendorID = CWProtocolRetrieve32(msgPtr);\t// ID\n\ttheOffset = msgPtr->offset;\n\twhile ((msgPtr->offset - oldOffset) < len) {\t// oldOffset stores msgPtr->offset's value at the beginning of this function.\n\t\t// See the definition of the CWParseMessageElementStart() macro.\n\t\tint tmp;\n\n\t\tCWProtocolRetrieve16(msgPtr);\t// type\n\t\ttmp = CWProtocolRetrieve16(msgPtr);\n\t\tmsgPtr->offset += tmp;\t// len\n\t\tvalPtr->vendorInfosCount++;\n\t}\n\n\tmsgPtr->offset = theOffset;\n\n\t// actually read each vendor ID\n\tCW_CREATE_ARRAY_ERR(valPtr->vendorInfos, valPtr->vendorInfosCount, CWWTPVendorInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < valPtr->vendorInfosCount; i++) {\n\t\t(valPtr->vendorInfos)[i].vendorIdentifier = vendorID;\n\t\t(valPtr->vendorInfos)[i].type = CWProtocolRetrieve16(msgPtr);\n\t\t(valPtr->vendorInfos)[i].length = CWProtocolRetrieve16(msgPtr);\n\t\t(valPtr->vendorInfos)[i].valuePtr =\n\t\t    (CWProtocolRetrieveRawBytes(msgPtr, (valPtr->vendorInfos)[i].length));\n\n\t\tif ((valPtr->vendorInfos)[i].valuePtr == NULL)\n\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\n\t\tif ((valPtr->vendorInfos)[i].length == 4) {\n\t\t\t*(int *)((valPtr->vendorInfos)[i].valuePtr) = ntohl(*((valPtr->vendorInfos)[i].valuePtr));\n\t\t}\n//      CWDebugLog(\"WTP Board Data: %d - %d - %d - %d\", (valPtr->vendorInfos)[i].vendorIdentifier, (valPtr->vendorInfos)[i].type, (valPtr->vendorInfos)[i].length, *(valPtr->vendorInfos)[i].valuePtr);\n\t}\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseMsgElemDataTransferData(CWProtocolMessage * msgPtr, int len,\n\t\t\t\t      CWProtocolWTPDataTransferRequestValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->data = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->length = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->debug_info = CWProtocolRetrieveStr(msgPtr, valPtr->length);\n\t//CWDebugLog(\"- %s ---\",valPtr->debug_info);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPDescriptor(CWProtocolMessage * msgPtr, int len, CWWTPDescriptor * valPtr)\n{\n\tint theOffset, i;\n\tCWParseMessageElementStart();\n\n\tvalPtr->maxRadios = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"WTP Descriptor Max Radios: %d\", valPtr->maxRadios);\n\n\tvalPtr->radiosInUse = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"WTP Descriptor Active Radios: %d\",  valPtr->radiosInUse);\n\n\tvalPtr->encCapabilities.encryptCapsCount = CWProtocolRetrieve8(msgPtr);\n\tCW_CREATE_ARRAY_ERR(valPtr->encCapabilities.encryptCaps, valPtr->encCapabilities.encryptCapsCount,\n\t\t\t    CWWTPEncryptCapValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL); );\n\tfor (i = 0; i < valPtr->encCapabilities.encryptCapsCount; i++) {\n\t\t(valPtr->encCapabilities.encryptCaps)[i].WBID = CWProtocolRetrieve8(msgPtr) & 0x1f;\n\t\t(valPtr->encCapabilities.encryptCaps)[i].encryptionCapabilities = CWProtocolRetrieve16(msgPtr);\n\t}\n\n\tvalPtr->vendorInfos.vendorInfosCount = 0;\n\ttheOffset = msgPtr->offset;\n\n\t// see how many vendor ID we have in the message\n\twhile ((msgPtr->offset - oldOffset) < len) {\t// oldOffset stores msgPtr->offset's value at the beginning of this function.\n\t\t// See the definition of the CWParseMessageElementStart() macro.\n\t\tint tmp;\n\t\tCWProtocolRetrieve32(msgPtr);\t// ID\n\t\tCWProtocolRetrieve16(msgPtr);\t// type\n\t\ttmp = CWProtocolRetrieve16(msgPtr);\t// len\n\t\tmsgPtr->offset += tmp;\n\t\tvalPtr->vendorInfos.vendorInfosCount++;\n\t}\n\n\tmsgPtr->offset = theOffset;\n\n\t// actually read each vendor ID\n\tCW_CREATE_ARRAY_ERR(valPtr->vendorInfos.vendorInfos, valPtr->vendorInfos.vendorInfosCount,\n\t\t\t    CWWTPVendorInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < valPtr->vendorInfos.vendorInfosCount; i++) {\n\t\t(valPtr->vendorInfos.vendorInfos)[i].vendorIdentifier = CWProtocolRetrieve32(msgPtr);\n\t\t(valPtr->vendorInfos.vendorInfos)[i].type = CWProtocolRetrieve16(msgPtr);\n\t\t(valPtr->vendorInfos.vendorInfos)[i].length = CWProtocolRetrieve16(msgPtr);\n\t\t(valPtr->vendorInfos.vendorInfos)[i].valuePtr =\n\t\t    (CWProtocolRetrieveRawBytes(msgPtr, (valPtr->vendorInfos.vendorInfos)[i].length));\n\n\t\tif ((valPtr->vendorInfos.vendorInfos)[i].valuePtr == NULL)\n\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\n\t\tif ((valPtr->vendorInfos.vendorInfos)[i].length == 4) {\n\t\t\t*((valPtr->vendorInfos.vendorInfos)[i].valuePtr) =\n\t\t\t    ntohl(*((valPtr->vendorInfos.vendorInfos)[i].valuePtr));\n\t\t}\n//      CWDebugLog(\"WTP Descriptor Vendor ID: %d\", (valPtr->vendorInfos.vendorInfos)[i].vendorIdentifier);\n//      CWDebugLog(\"WTP Descriptor Type: %d\", (valPtr->vendorInfos.vendorInfos)[i].type);\n//      CWDebugLog(\"WTP Descriptor Length: %d\", (valPtr->vendorInfos.vendorInfos)[i].length);\n//      CWDebugLog(\"WTP Descriptor Value: %d\", *((valPtr->vendorInfos.vendorInfos)[i].valuePtr));\n\t}\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPFrameTunnelMode(CWProtocolMessage * msgPtr, int len, CWframeTunnelMode * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*valPtr = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"CW_MSG_ELEMENT_WTP_FRAME_ENCAPSULATION_TYPE: %d\", valPtr->frameTunnelMode);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPIPv4Address(CWProtocolMessage * msgPtr, int len, CWProtocolJoinRequestValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->addr.sin_addr.s_addr = htonl(CWProtocolRetrieve32(msgPtr));\n\tvalPtr->addr.sin_family = AF_INET;\n\tvalPtr->addr.sin_port = htons(CW_CONTROL_PORT);\n//  CWDebugLog(\"WTP Address: %s\", sock_ntop((struct sockaddr*) (&(valPtr->addr)), sizeof(valPtr->addr)));\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPMACType(CWProtocolMessage * msgPtr, int len, CWMACType * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*valPtr = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"CW_MSG_ELEMENT_WTP_MAC_TYPE: %d\",   valPtr->MACType);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPRadioInformation(CWProtocolMessage * msgPtr, int len, unsigned char *valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tCWProtocolRetrieve8(msgPtr);\t// Radio ID\n\tCWProtocolRetrieve8(msgPtr);\t// Res\n\tCWProtocolRetrieve8(msgPtr);\t// Res\n\tCWProtocolRetrieve8(msgPtr);\t// Res\n\t*valPtr = CWProtocolRetrieve8(msgPtr);\t// Radio Information\n\n\tCWParseMessageElementEnd();\n\n}\n\nCWBool CWParseWTPSupportedRates(CWProtocolMessage * msgPtr, int len, unsigned char *valPtr)\n{\n\n\tCWParseMessageElementStart();\n\tunsigned char sup_rates[8];\n\n\tCWProtocolRetrieve8(msgPtr);\n\n\tsup_rates[0] = CWProtocolRetrieve8(msgPtr);\n\tsup_rates[1] = CWProtocolRetrieve8(msgPtr);\n\tsup_rates[2] = CWProtocolRetrieve8(msgPtr);\n\tsup_rates[3] = CWProtocolRetrieve8(msgPtr);\n\tsup_rates[4] = CWProtocolRetrieve8(msgPtr);\n\tsup_rates[5] = CWProtocolRetrieve8(msgPtr);\n\tsup_rates[6] = CWProtocolRetrieve8(msgPtr);\n\tsup_rates[7] = CWProtocolRetrieve8(msgPtr);\n\n\tmemcpy(valPtr, sup_rates, 8);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPMultiDomainCapability(CWProtocolMessage * msgPtr, int len, char *valPtr)\n{\n\n\tCWParseMessageElementStart();\n\tunsigned char sup_cap[6];\n\n\tCWProtocolRetrieve8(msgPtr);\n\tCWProtocolRetrieve8(msgPtr);\n\n\tsup_cap[0] = CWProtocolRetrieve8(msgPtr);\n\tsup_cap[1] = CWProtocolRetrieve8(msgPtr);\n\tsup_cap[2] = CWProtocolRetrieve8(msgPtr);\n\tsup_cap[3] = CWProtocolRetrieve8(msgPtr);\n\tsup_cap[4] = CWProtocolRetrieve8(msgPtr);\n\tsup_cap[5] = CWProtocolRetrieve8(msgPtr);\n\n\tmemcpy(valPtr, sup_cap, 6);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPName(CWProtocolMessage * msgPtr, int len, char **valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*valPtr = CWProtocolRetrieveStr(msgPtr, len);\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n//  CWDebugLog(\"WTP Name:%s\", *valPtr);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPRebootStatistics(CWProtocolMessage * msgPtr, int len, WTPRebootStatisticsInfo * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->rebootCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->ACInitiatedCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->linkFailurerCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->SWFailureCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->HWFailuireCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->otherFailureCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->unknownFailureCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->lastFailureType = CWProtocolRetrieve8(msgPtr);\n\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"WTPRebootStat(1): %d - %d - %d\", valPtr->rebootCount, valPtr->ACInitiatedCount, valPtr->linkFailurerCount);\n//  CWDebugLog(\"WTPRebootStat(2): %d - %d - %d\", valPtr->SWFailureCount, valPtr->HWFailuireCount, valPtr->otherFailureCount);\n//  CWDebugLog(\"WTPRebootStat(3): %d - %d\", valPtr->unknownFailureCount, valPtr->lastFailureType);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPRadioStatistics(CWProtocolMessage * msgPtr, int len, WTPRadioStatisticsValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->radioID = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->WTPRadioStatistics.lastFailureType = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->WTPRadioStatistics.resetCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.SWFailureCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.HWFailuireCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.otherFailureCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.unknownFailureCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.configUpdateCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.channelChangeCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.bandChangeCount = CWProtocolRetrieve16(msgPtr);\n\tvalPtr->WTPRadioStatistics.currentNoiseFloor = CWProtocolRetrieve16(msgPtr);\n\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"WTPRadioStatistics of radio: \\\"%d\\\"\", valPtr->radioID);\n//  CWDebugLog(\"WTPRadioStatistics(1): %d - %d - %d\", valPtr->WTPRadioStatistics.lastFailureType, valPtr->WTPRadioStatistics.resetCount, valPtr->WTPRadioStatistics.SWFailureCount);\n//  CWDebugLog(\"WTPRadioStatistics(2): %d - %d - %d\", valPtr->WTPRadioStatistics.HWFailuireCount, valPtr->WTPRadioStatistics.otherFailureCount, valPtr->WTPRadioStatistics.unknownFailureCount);\n//  CWDebugLog(\"WTPRadioStatistics(3): %d - %d - %d - %d\", valPtr->WTPRadioStatistics.configUpdateCount, valPtr->WTPRadioStatistics.channelChangeCount, valPtr->WTPRadioStatistics.bandChangeCount, valPtr->WTPRadioStatistics.currentNoiseFloor);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPOperationalStatistics(CWProtocolMessage * msgPtr, int len, WTPOperationalStatisticsValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->radioID = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->TxQueueLevel = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->wirelessLinkFramesPerSec = CWProtocolRetrieve16(msgPtr);\n\n//  CWDebugLog(\"WTPOperationalStatistics of radio \\\"%d\\\": %d - %d\", valPtr->radioID, valPtr->TxQueueLevel, valPtr->wirelessLinkFramesPerSec);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseMsgElemDecryptErrorReport(CWProtocolMessage * msgPtr, int len, CWDecryptErrorReportValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->ID = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->numEntries = CWProtocolRetrieve8(msgPtr);\n\n\tvalPtr->length = CWProtocolRetrieve8(msgPtr);\n\n\tvalPtr->decryptErrorMACAddressList = NULL;\n\tif ((valPtr->numEntries) > 0) {\n\t\tCW_CREATE_ARRAY_ERR(valPtr->decryptErrorMACAddressList, valPtr->numEntries, CWMACAddress,\n\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tint size = sizeof(CWMACAddress) * (valPtr->numEntries);\n\t\tCW_COPY_MEMORY(valPtr->decryptErrorMACAddressList, CWProtocolRetrieveRawBytes(msgPtr, size), size);\n\t\t//valPtr->decryptErrorMACAddressList =(unsigned char*) CWProtocolRetrieveRawBytes(msgPtr, sizeof(CWMACAddress)*(valPtr->numEntries));\n\t\t//CW_COPY_MEMORY(&((valPtr->ACIPv6List)[i]), CWProtocolRetrieveRawBytes(msgPtr, 16), 16);\n\t\t/*\n\t\t   int j;\n\t\t   for (j=0;j<(sizeof(CWMACAddress)*(valPtr->numEntries)); j++)\n\t\t   CWDebugLog(\"##(%d/6) = %d\", j%6, (valPtr->decryptErrorMACAddressList)[j/6][j%6]);\n\t\t */\n\t}\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"Radio Decrypt Error Report of radio \\\"%d\\\": %d\", valPtr->ID, valPtr->numEntries);\n\n\tCWParseMessageElementEnd();\n}\n\n/*\nCWBool CWParseWTPRadioInfo(CWPr<otocolMessage *msgPtr, int len, CWRadiosInformation *valPtr, int radioIndex) {\n    CWParseMessageElementStart();\n\n    (valPtr->radios)[radioIndex].ID = CWProtocolRetrieve8(msgPtr);\n    (valPtr->radios)[radioIndex].type = CWProtocolRetrieve32(msgPtr);\n\n    CWDebugLog(\"WTP Radio info: %d %d \", (valPtr->radios)[radioIndex].ID, (valPtr->radios)[radioIndex].type);\n\n    CWParseMessageElementEnd();\n}\n*/\n"
  },
  {
    "path": "ACProtocol.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_ACProtocol_HEADER__\n#define __CAPWAP_ACProtocol_HEADER__\n\n//#define UNUSED_RADIO_ID   1000\n\ntypedef struct {\n\tchar *locationData;\n\tchar *name;\n\tunsigned char *sessionID;\n\tCWWTPDescriptor descriptor;\n\tstruct sockaddr_in ipv4Address;\n\n\tCWWTPRadiosInfo radiosInfo;\n\n\tchar *ACName;\n\tCWACNamesWithIndex ACNameIndex;\n\tCWRadiosAdminInfo radioAdminInfo;\n\tint StatisticsTimer;\n\tCWWTPVendorInfos WTPBoardData;\n\t//CWRadiosInformation WTPRadioInfo;\n\tWTPRebootStatisticsInfo *WTPRebootStatistics;\n\n\tvoid *bindingValuesPtr;\n} CWWTPProtocolManager;\n\ntypedef struct {\n\tchar *location;\n\tchar *name;\n\tCWWTPVendorInfos WTPBoardData;\n\tunsigned char *sessionID;\n\tCWWTPDescriptor WTPDescriptor;\n\tstruct sockaddr_in addr;\n\tCWframeTunnelMode frameTunnelMode;\n\tCWMACType MACType;\n\n} CWProtocolJoinRequestValues;\n\ntypedef struct {\n\tchar *ACName;\n\tCWACNamesWithIndex ACinWTP;\n\tint radioAdminInfoCount;\n\tCWRadioAdminInfoValues *radioAdminInfo;\n\tint StatisticsTimer;\n\tWTPRebootStatisticsInfo *WTPRebootStatistics;\n\n} CWProtocolConfigureRequestValues;\n\ntypedef struct {\n\tCWRadiosOperationalInfo radioOperationalInfo;\n\tCWProtocolResultCode resultCode;\n} CWProtocolChangeStateEventRequestValues;\n\ntypedef struct {\n\tunsigned int radioID;\n\tunsigned int TxQueueLevel;\n\tunsigned int wirelessLinkFramesPerSec;\n} WTPOperationalStatisticsValues;\n\ntypedef struct {\n\tunsigned int radioID;\n\tWTPRadioStatisticsInfo WTPRadioStatistics;\n} WTPRadioStatisticsValues;\n\ntypedef struct {\n\tint ipv4Address;\n\tunsigned int length;\n\tunsigned char *MACoffendingDevice_forIpv4;\n\tint status;\n} WTPDuplicateIPv4;\n\ntypedef struct {\n\tstruct in6_addr ipv6Address;\n\tunsigned int length;\n\tunsigned char *MACoffendingDevice_forIpv6;\n\tint status;\n} WTPDuplicateIPv6;\n\ntypedef struct {\n\tint errorReportCount;\n\tCWDecryptErrorReportValues *errorReport;\n\tWTPDuplicateIPv4 *duplicateIPv4;\n\tWTPDuplicateIPv6 *duplicateIPv6;\n\tint WTPOperationalStatisticsCount;\n\tWTPOperationalStatisticsValues *WTPOperationalStatistics;\n\tint WTPRadioStatisticsCount;\n\tWTPRadioStatisticsValues *WTPRadioStatistics;\n\tWTPRebootStatisticsInfo *WTPRebootStatistics;\n} CWProtocolWTPEventRequestValues;\n\ntypedef struct {\n\n\tint data;\n\tint length;\n\tchar *debug_info;\n} CWProtocolWTPDataTransferRequestValues;\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\nCWBool CWParseChangeStateEventRequestMessage(unsigned char *msg, int len, int *seqNumPtr,\n\t\t\t\t\t     CWProtocolChangeStateEventRequestValues * valuesPtr);\nCWBool CWAssembleChangeStateEventResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum);\n\nCWBool CWAssembleMsgElemACDescriptor(CWProtocolMessage * msgPtr);\t// 1\nCWBool CWAssembleMsgElemACIPv4List(CWProtocolMessage * msgPtr);\t// 2\nCWBool CWAssembleMsgElemACIPv6List(CWProtocolMessage * msgPtr);\t// 3\nCWBool CWAssembleMsgElemACName(CWProtocolMessage * msgPtr);\t// 4\nCWBool CWAssembleMsgElemAddStation(int radioID, CWProtocolMessage * msgPtr, unsigned char *StationMacAddr);\t// 8\nCWBool CWAssembleMsgElemDeleteStation(int radioID, CWProtocolMessage * msgPtr, unsigned char *StationMacAddr);\t// 8\nCWBool CWAssembleMsgElemCWControlIPv4Addresses(CWProtocolMessage * msgPtr);\t//10\nCWBool CWAssembleMsgElemCWControlIPv6Addresses(CWProtocolMessage * msgPtr);\t//11\nCWBool CWAssembleMsgElemCWTimer(CWProtocolMessage * msgPtr);\t//12\nCWBool CWAssembleMsgElemDecryptErrorReportPeriod(CWProtocolMessage * msgPtr);\t//16\nCWBool CWAssembleMsgElemIdleTimeout(CWProtocolMessage * msgPtr);\t//23\nCWBool CWAssembleMsgElemWTPFallback(CWProtocolMessage * msgPtr);\t//37\nCWBool CWAssembleWLANConfigurationRequest(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum,\n\t\t\t\t\t  unsigned char *recv_packet, int Operation, int len_packet);\nCWBool CWAssembleMsgElemACWTPRadioInformation(CWProtocolMessage * msgPtr);\nCWBool CWAssembleMsgElemAddWLAN(int radioID, CWProtocolMessage * msgPtr, unsigned char *recv_packet, int len_packet);\nCWBool CWAssembleMsgElemDeleteWLAN(int radioID, CWProtocolMessage * msgPtr, unsigned char *recv_packet, int len_packet);\n\n//---------------------------------------------------------/\n\n//CWBool CWParseACName(CWProtocolMessage *msgPtr, int len, char **valPtr);\nCWBool CWParseACNameWithIndex(CWProtocolMessage * msgPtr, int len, CWACNameWithIndexValues * valPtr);\t// 5\nCWBool CWParseMsgElemDataTransferData(CWProtocolMessage * msgPtr, int len, CWProtocolWTPDataTransferRequestValues * valPtr);\t//13\nCWBool CWParseDiscoveryType(CWProtocolMessage * msgPtr, int len, CWDiscoveryRequestValues * valPtr);\t//20\nCWBool CWParseMsgElemDuplicateIPv4Address(CWProtocolMessage * msgPtr, int len, WTPDuplicateIPv4 * valPtr);\t//21\nCWBool CWParseLocationData(CWProtocolMessage * msgPtr, int len, char **valPtr);\t//27\nCWBool CWParseWTPRadioAdminState(CWProtocolMessage * msgPtr, int len, CWRadioAdminInfoValues * valPtr);\t//29\nCWBool CWParseWTPStatisticsTimer(CWProtocolMessage * msgPtr, int len, int *valPtr);\t//33\nCWBool CWParseWTPBoardData(CWProtocolMessage * msgPtr, int len, CWWTPVendorInfos * valPtr);\t//35\nCWBool CWParseWTPDescriptor(CWProtocolMessage * msgPtr, int len, CWWTPDescriptor * valPtr);\t//37\nCWBool CWParseWTPFrameTunnelMode(CWProtocolMessage * msgPtr, int len, CWframeTunnelMode * valPtr);\t//38\nCWBool CWParseWTPIPv4Address(CWProtocolMessage * msgPtr, int len, CWProtocolJoinRequestValues * valPtr);\t//39\nCWBool CWParseWTPMACType(CWProtocolMessage * msgPtr, int len, CWMACType * valPtr);\t//40\nCWBool CWParseWTPName(CWProtocolMessage * msgPtr, int len, char **valPtr);\t//41\nCWBool CWParseWTPOperationalStatistics(CWProtocolMessage * msgPtr, int len, WTPOperationalStatisticsValues * valPtr);\t//42\nCWBool CWParseWTPRadioStatistics(CWProtocolMessage * msgPtr, int len, WTPRadioStatisticsValues * valPtr);\t//43\nCWBool CWParseWTPRebootStatistics(CWProtocolMessage * msgPtr, int len, WTPRebootStatisticsInfo * valPtr);\t//44\nCWBool CWParseMsgElemDecryptErrorReport(CWProtocolMessage * msgPtr, int len, CWDecryptErrorReportValues * valPtr);\nCWBool CWParseMsgElemDuplicateIPv6Address(CWProtocolMessage * msgPtr, int len, WTPDuplicateIPv6 * valPtr);\nCWBool CWParseWTPRadioInformation(CWProtocolMessage * msgPtr, int len, unsigned char *valPtr);\t//1048\nCWBool CWParseWTPSupportedRates(CWProtocolMessage * msgPtr, int len, unsigned char *valPtr);\t//1040\nCWBool CWParseWTPMultiDomainCapability(CWProtocolMessage * msgPtr, int len, char *valPtr);\t//1032\n//CWBool CWParseWTPRadioInfo(CWProtocolMessage *msgPtr, int len, CWRadiosInformation *valPtr, int radioIndex);\n\n//---------------------------------------------------------/\nCWBool CWACGetACIPv4List(int **listPtr, int *countPtr);\nCWBool CWACGetACIPv6List(struct in6_addr **listPtr, int *countPtr);\nchar *CWACGetName(void);\nint CWACGetHWVersion(void);\nint CWACGetSWVersion(void);\nint CWACGetStations(void);\nint CWACGetLimit(void);\nint CWACGetActiveWTPs(void);\nint CWACGetMaxWTPs(void);\nint CWACGetSecurity(void);\nint CWACGetInterfacesCount(void);\nint CWACGetInterfaceIPv4AddressAtIndex(int i);\nunsigned char *CWACGetInterfaceIPv6AddressAtIndex(int i);\nint CWACGetInterfaceWTPCountAtIndex(int i);\nCWBool CWACGetDiscoveryTimer(int *timer);\nCWBool CWACGetEchoRequestTimer(int *timer);\nCWBool CWACGetIdleTimeout(int *timer);\nCWBool CWGetWTPRadiosOperationalState(int radioID, CWRadiosOperationalInfo * valPtr);\n\n//---------------------------------------------------------/\nCWBool CWACSupportIPv6();\nvoid CWDestroyDiscoveryRequestValues(CWDiscoveryRequestValues * valPtr);\n\nCWBool CWProtocolAssembleConfigurationUpdateRequest(CWProtocolMessage ** msgElems, int *msgElemCountPtr,\n\t\t\t\t\t\t    int MsgElementType);\n\n#endif\n"
  },
  {
    "path": "ACProtocol_User.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n__inline__ CWBool CWACSupportIPv6()\n{\n\treturn (gNetworkPreferredFamily == CW_IPv6);\n}\n\n__inline__ char *CWACGetName()\n{\n\treturn gACName;\n}\n\n__inline__ int CWACGetStations()\n{\n\treturn gActiveStations;\n}\n\n__inline__ int CWACGetLimit()\n{\n\treturn gLimit;\n}\n\n__inline__ int CWACGetActiveWTPs()\n{\n\tint tmp;\n\tif (!CWErr(CWThreadMutexLock(&gActiveWTPsMutex)))\n\t\treturn 0;\n\ttmp = gActiveWTPs;\n\tCWThreadMutexUnlock(&gActiveWTPsMutex);\n\n\treturn tmp;\n}\n\n__inline__ int CWACGetMaxWTPs()\n{\n\treturn gMaxWTPs;\n}\n\n__inline__ int CWACGetSecurity()\n{\n\treturn gACDescriptorSecurity;\n}\n\n__inline__ int CWACGetRMACField()\n{\n\treturn gRMACField;\n}\n\n__inline__ int CWACGetWirelessField()\n{\n\treturn gWirelessField;\n}\n\n__inline__ int CWACGetDTLSPolicy()\n{\n\treturn gDTLSPolicy;\n}\n\n__inline__ int CWACGetHWVersion()\n{\n\treturn gACHWVersion;\n}\n\n__inline__ int CWACGetSWVersion()\n{\n\treturn gACSWVersion;\n}\n\n__inline__ int CWACGetInterfacesCount()\n{\n\treturn gInterfacesCount;\n}\n\n__inline__ int CWACGetInterfaceIPv4AddressAtIndex(int i)\n{\n\tstruct sockaddr_in *addrPtr;\n\n\tif (gNetworkPreferredFamily == CW_IPv4) {\n\t\taddrPtr = (struct sockaddr_in *)&(gInterfaces[i].addr);\n\t} else {\n\t\taddrPtr = (struct sockaddr_in *)&(gInterfaces[i].addrIPv4);\n\t}\n\n\treturn ntohl(addrPtr->sin_addr.s_addr);\n}\n\n__inline__ unsigned char *CWACGetInterfaceIPv6AddressAtIndex(int i)\n{\n\tstruct sockaddr_in6 *addrPtr;\n\n\taddrPtr = (struct sockaddr_in6 *)&(gInterfaces[i].addr);\n\n\treturn addrPtr->sin6_addr.s6_addr;\n}\n\n__inline__ int CWACGetInterfaceWTPCountAtIndex(int i)\n{\n\treturn gInterfaces[i].WTPCount;\n}\n\nCWBool CWACGetVendorInfos(CWACVendorInfos * valPtr)\n{\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tvalPtr->vendorInfosCount = 2;\n\tCW_CREATE_ARRAY_ERR((valPtr->vendorInfos), valPtr->vendorInfosCount, CWACVendorInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t// my vendor identifier (IANA assigned \"SMI Network Management Private Enterprise Code\")\n\t(valPtr->vendorInfos)[0].vendorIdentifier = 65432;\n\t(valPtr->vendorInfos)[0].type = CW_AC_HARDWARE_VERSION;\n\t(valPtr->vendorInfos)[0].length = 4;\t// just one int\n\tCW_CREATE_OBJECT_SIZE_ERR((((valPtr->vendorInfos)[0]).valuePtr), 4,\n\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*(((valPtr->vendorInfos)[0]).valuePtr) = CWACGetHWVersion();\t// HW version\n\n\t// my vendor identifier (IANA assigned \"SMI Network Management Private Enterprise Code\")\n\t((valPtr->vendorInfos)[1]).vendorIdentifier = 65432;\n\t((valPtr->vendorInfos)[1]).type = CW_AC_SOFTWARE_VERSION;\n\t((valPtr->vendorInfos)[1]).length = 4;\t// just one int\n\tCW_CREATE_OBJECT_SIZE_ERR((((valPtr->vendorInfos)[1]).valuePtr), 4,\n\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*(((valPtr->vendorInfos)[1]).valuePtr) = CWACGetSWVersion();\t// SW version\n\n\treturn CW_TRUE;\n}\n\n__inline__ void CWACDestroyVendorInfos(CWACVendorInfos * valPtr)\n{\n\tint i;\n\n\tif (valPtr == NULL)\n\t\treturn;\n\n\tfor (i = 0; i < valPtr->vendorInfosCount; i++) {\n\t\tCW_FREE_OBJECT((valPtr->vendorInfos)[i].valuePtr);\n\t}\n\n\tCW_FREE_OBJECT(valPtr->vendorInfos);\n}\n\nCWBool CWACGetACIPv4List(int **listPtr, int *countPtr)\n{\n\tstruct in_addr addr;\n\n\t// TO-DO this func should return the addresses of eventual other ACs in a cluster. Hey, what? What is the WTP\n\t// supposed to do with that?\n\tif (listPtr == NULL || countPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t*countPtr = 2;\n\n\tCW_CREATE_ARRAY_ERR((*listPtr), (*countPtr), int, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tinet_pton(AF_INET, \"192.168.1.2\", &addr);\t// TO-DO take the addresses from config file?\n\t(*listPtr)[0] = addr.s_addr;\n\tinet_pton(AF_INET, \"192.168.1.66\", &addr);\n\t(*listPtr)[1] = addr.s_addr;\n\n\treturn CW_TRUE;\n}\n\nCWBool CWACGetACIPv6List(struct in6_addr ** listPtr, int *countPtr)\n{\n\t// TO-DO this func should return the addresses of eventual other ACs in a cluster. Hey, what? What is the WTP\n\t// supposed to do with that?\n\tif (listPtr == NULL || countPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t*countPtr = 2;\n\n\tCW_CREATE_ARRAY_ERR(*listPtr, (*countPtr), struct in6_addr, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tinet_pton(AF_INET6, \"5f1b:df00:ce3e:e200:0020:0800:2078:e3e3\", &((*listPtr)[0]));\t// TO-DO take the addresses from config file?\n\tinet_pton(AF_INET6, \"5f1b:df00:ce3e:e200:0020:0800:2078:e3e4\", &((*listPtr)[1]));\n\n\treturn CW_TRUE;\n}\n\nCWBool CWACGetDiscoveryTimer(int *timer)\n{\n\t*timer = gDiscoveryTimer;\n\treturn CW_TRUE;\n}\n\nCWBool CWACGetEchoRequestTimer(int *timer)\n{\n\t*timer = gEchoRequestTimer;\n\treturn CW_TRUE;\n}\n\nCWBool CWACGetIdleTimeout(int *timer)\n{\n\t*timer = gIdleTimeout;\n\treturn CW_TRUE;\n}\n\n/* Il WTP ha la funzione ridefinita */\nCWBool CWGetWTPRadiosAdminState(CWRadiosAdminInfo * valPtr)\n{\n\tint *WTPIndexPtr;\n\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((WTPIndexPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\n\tvalPtr->radiosCount = gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radioCount;\n\n\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWRadioAdminInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tint i;\n\tfor (i = 0; i < valPtr->radiosCount; i++) {\n\t\t(valPtr->radios)[i].ID = gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].radioID;\n\t\t(valPtr->radios)[i].state = gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].adminState;\n\t\t(valPtr->radios)[i].cause = gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].adminCause;\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWGetWTPRadiosOperationalState(int radioID, CWRadiosOperationalInfo * valPtr)\n{\n\tint i;\n\tCWBool found = CW_FALSE;\n\tint *WTPIndexPtr;\n\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((WTPIndexPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (radioID < 0) {\n\t\tvalPtr->radiosCount = gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radioCount;\n\n\t\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWRadioOperationalInfoValues,\n\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tfor (i = 0; i < valPtr->radiosCount; i++) {\n\t\t\t(valPtr->radios)[i].ID =\n\t\t\t    gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].radioID;\n\t\t\t(valPtr->radios)[i].state =\n\t\t\t    gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].operationalState;\n\t\t\t(valPtr->radios)[i].cause =\n\t\t\t    gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].operationalCause;\n\t\t}\n\t\treturn CW_TRUE;\n\t} else {\n\t\tfor (i = 0; i < valPtr->radiosCount; i++) {\n\t\t\tif (gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].radioID == radioID) {\n\t\t\t\tfound = CW_TRUE;\n\t\t\t\tvalPtr->radiosCount = 1;\n\t\t\t\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWRadioOperationalInfoValues,\n\t\t\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\t(valPtr->radios)[i].ID =\n\t\t\t\t    gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].radioID;\n\t\t\t\t(valPtr->radios)[i].state =\n\t\t\t\t    gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].operationalState;\n\t\t\t\t(valPtr->radios)[i].cause =\n\t\t\t\t    gWTPs[*WTPIndexPtr].WTPProtocolManager.radiosInfo.radiosInfo[i].operationalCause;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn found;\n\t}\n}\n"
  },
  {
    "path": "ACRetransmission.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWAC.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/*\n * CW_FREE_WTP_MSG_ARRAY - free the array of the messages\n * to be sent relative to the WTP with the specified index.\n *\n * ref -> BUG ML12\n * 20/10/2009 - Donato Capitella\n */\nstatic void inline CW_FREE_WTP_MSG_ARRAY(int WTPIndex)\n{\n\tint i;\n\tfor (i = 0; i < gWTPs[WTPIndex].messagesCount; i++) {\n\t\tCW_FREE_OBJECT(gWTPs[WTPIndex].messages[i].msg);\n\t}\n\tCW_FREE_OBJECT(gWTPs[WTPIndex].messages);\n\tgWTPs[WTPIndex].messagesCount = 0;\n}\n\nCWBool CWACSendFragments(int WTPIndex)\n{\n\tint i;\n\n\tif (gWTPs[WTPIndex].messages == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tfor (i = 0; i < gWTPs[WTPIndex].messagesCount; i++) {\n#ifdef CW_NO_DTLS\n\t\tif (!CWNetworkSendUnsafeUnconnected(gWTPs[WTPIndex].socket,\n\t\t\t\t\t\t    &gWTPs[WTPIndex].address,\n\t\t\t\t\t\t    gWTPs[WTPIndex].messages[i].msg,\n\t\t\t\t\t\t    gWTPs[WTPIndex].messages[i].offset)) {\n#else\n\t\tif (!\n\t\t    (CWSecuritySend\n\t\t     (gWTPs[WTPIndex].session, gWTPs[WTPIndex].messages[i].msg, gWTPs[WTPIndex].messages[i].offset))) {\n#endif\n\t\t\treturn CW_FALSE;\n\t\t}\n\t}\n\n\t/*\n\t * BUG - ML12\n\t *\n\t * 20/10/2009 - Donato Capitella\n\t */\n\tCW_FREE_WTP_MSG_ARRAY(WTPIndex);\n\n\tCWLog(\"Message Sent\\n\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWACResendAcknowledgedPacket(int WTPIndex)\n{\n\tif (!CWACSendFragments(WTPIndex))\n\t\treturn CW_FALSE;\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\tif (!\n\t    (CWTimerRequest\n\t     (gCWRetransmitTimer, &(gWTPs[WTPIndex].thread), &(gWTPs[WTPIndex].currentPacketTimer),\n\t      CW_SOFT_TIMER_EXPIRED_SIGNAL))) {\n\t\treturn CW_FALSE;\n\t}\n\tCWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\treturn CW_TRUE;\n}\n\n__inline__ CWBool CWACSendAcknowledgedPacket(int WTPIndex, int msgType, int seqNum)\n{\n\tgWTPs[WTPIndex].retransmissionCount = 0;\n\tgWTPs[WTPIndex].isRetransmitting = CW_TRUE;\n\tgWTPs[WTPIndex].responseType = msgType;\n\tgWTPs[WTPIndex].responseSeqNum = seqNum;\n//  CWDebugLog(\"~~~~~~seq num in Send: %d~~~~~~\", gWTPs[WTPIndex].responseSeqNum);\n\treturn CWACResendAcknowledgedPacket(WTPIndex);\n}\n\nvoid CWACStopRetransmission(int WTPIndex)\n{\n\tif (gWTPs[WTPIndex].isRetransmitting) {\n\t\tint i;\n\t\tCWDebugLog(\"Stop Retransmission\");\n\t\tgWTPs[WTPIndex].isRetransmitting = CW_FALSE;\n\t\tCWThreadSetSignals(SIG_BLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\t\tif (!CWTimerCancel(&(gWTPs[WTPIndex].currentPacketTimer))) {\n\t\t\tCWDebugLog(\"Error Cancelling a Timer... possible error!\");\n\t\t}\n\t\tCWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\t\tgWTPs[WTPIndex].responseType = UNUSED_MSG_TYPE;\n\t\tgWTPs[WTPIndex].responseSeqNum = 0;\n\n\t\tfor (i = 0; i < gWTPs[WTPIndex].messagesCount; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(gWTPs[WTPIndex].messages[i]);\n\t\t}\n\n\t\tCW_FREE_OBJECT(gWTPs[WTPIndex].messages);\n//      CWDebugLog(\"~~~~~~ End of Stop Retransmission\");\n\t}\n}\n"
  },
  {
    "path": "ACRunState.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#include \"CWAC.h\"\n#include \"ACipcHostapd.h\"\n#include \"CWVendorPayloads.h\"\n#include \"CWFreqPayloads.h\"\n#include \"WUM.h\"\n#include \"common.h\"\n#include \"ieee802_11_defs.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool CWACParseGenericRunMessage(int WTPIndex, CWProtocolMessage * msg, CWControlHeaderValues * controlVal);\n\nCWBool CWParseConfigurationUpdateResponseMessage(CWProtocolMessage * msgPtr,\n\t\t\t\t\t\t int len,\n\t\t\t\t\t\t CWProtocolResultCode * resultCode,\n\t\t\t\t\t\t CWProtocolVendorSpecificValues ** protocolValues);\n\nCWBool CWSaveConfigurationUpdateResponseMessage(CWProtocolResultCode resultCode,\n\t\t\t\t\t\tint WTPIndex, CWProtocolVendorSpecificValues * protocolValues);\n\nCWBool CWParseClearConfigurationResponseMessage(CWProtocolMessage * msgPtr, int len, CWProtocolResultCode * resultCode);\n\nCWBool CWParseWLANConfigurationResponseMessage(CWProtocolMessage * msgPtr, int len, CWProtocolResultCode * resultCode);\n\nCWBool CWParseStationConfigurationResponseMessage(CWProtocolMessage * msgPtr,\n\t\t\t\t\t\t  int len, CWProtocolResultCode * resultCode);\n\nCWBool CWParseWTPDataTransferRequestMessage(CWProtocolMessage * msgPtr,\n\t\t\t\t\t    int len, CWProtocolWTPDataTransferRequestValues * valuesPtr);\n\nCWBool CWAssembleWTPDataTransferResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum);\n\nCWBool CWParseWTPEventRequestMessage(CWProtocolMessage * msgPtr, int len, CWProtocolWTPEventRequestValues * valuesPtr);\n\nCWBool CWSaveWTPEventRequestMessage(CWProtocolWTPEventRequestValues * WTPEventRequest,\n\t\t\t\t    CWWTPProtocolManager * WTPProtocolManager);\n\nCWBool CWAssembleWTPEventResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum);\n\nCWBool CWParseChangeStateEventRequestMessage2(CWProtocolMessage * msgPtr,\n\t\t\t\t\t      int len, CWProtocolChangeStateEventRequestValues ** valuesPtr);\n\nCWBool CWParseEchoRequestMessage(CWProtocolMessage * msgPtr, int len);\n\nCWBool CWAssembleEchoResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum);\n\nCWBool CWStartNeighborDeadTimer(int WTPIndex);\nCWBool CWStopNeighborDeadTimer(int WTPIndex);\nCWBool CWRestartNeighborDeadTimer(int WTPIndex);\nCWBool CWRestartNeighborDeadTimerForEcho(int WTPIndex);\n\nint flush_pcap(u_char * buf, int len, char *filename)\n{\n\n\tFILE *file;\n\tfile = fopen(filename, \"a+\");\n\tu_char index = 0x00;\n\tint cnt = 0;\n\tint i;\n\tint giro = 0;\n\tfor (i = 0; cnt < len; i++) {\n\t\tfprintf(file, \"0%02X0   \", index);\n\t\tfor (; cnt < len;) {\n\t\t\tfprintf(file, \"%02X \", buf[cnt]);\n\t\t\tcnt++;\n\t\t\tif (giro == 15) {\n\t\t\t\tgiro = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgiro++;\n\t\t}\n\t\tfprintf(file, \"\\n\");\n\t\tindex++;\n\t}\n\n\tfprintf(file, \"\\n\");\n\tfclose(file);\n\treturn 0;\n}\n\n#define HLEN_80211 24\nint isEAPOL_Frame(unsigned char *buf, int len)\n{\n\tunsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n\tint i;\n\n\tfor (i = 0; i < 6; i++)\n\t\tif (rfc1042_header[i] != buf[i + HLEN_80211])\n\t\t\treturn 0;\n\treturn 1;\n}\n\nCWBool ACEnterRun(int WTPIndex, CWProtocolMessage * msgPtr, CWBool dataFlag)\n{\n\n\tCWBool toSend = CW_FALSE, timerSet = CW_TRUE;\n\tCWControlHeaderValues controlVal;\n\tCWProtocolMessage *messages = NULL;\n\tint messagesCount = 0;\n\tunsigned char StationMacAddr[MAC_ADDR_LEN];\n\tchar string[10];\n\tchar socketctl_path_name[50];\n\tchar socketserv_path_name[50];\n\tint msglen = msgPtr->offset;\n\n\tmsgPtr->offset = 0;\n\tif (dataFlag) {\n\t\t/* We have received a Data Message... now just log this event and do actions by the dataType */\n\n\t\tCWDebugLog(\"--> Received a DATA Message\");\n\n\t\tif (msgPtr->data_msgType == CW_DATA_MSG_FRAME_TYPE) {\n\n\t\t\t/*Retrive mac address station from msg */\n\t\t\tmemset(StationMacAddr, 0, MAC_ADDR_LEN);\n\t\t\tmemcpy(StationMacAddr, msgPtr->msg + SOURCE_ADDR_START, MAC_ADDR_LEN);\n\n\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t//Send a Station Configuration Request\n\t\t\tif (CWAssembleStationConfigurationRequest(&(gWTPs[WTPIndex].messages),\n\t\t\t\t\t\t\t\t  &(gWTPs[WTPIndex].messagesCount),\n\t\t\t\t\t\t\t\t  gWTPs[WTPIndex].pathMTU,\n\t\t\t\t\t\t\t\t  seqNum, StationMacAddr,\n\t\t\t\t\t\t\t\t  CW_MSG_ELEMENT_ADD_STATION_CW_TYPE)) {\n\n\t\t\t\tif (CWACSendAcknowledgedPacket(WTPIndex,\n\t\t\t\t\t\t\t       CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE,\n\t\t\t\t\t\t\t       seqNum))\n\t\t\t\t\treturn CW_TRUE;\n\t\t\t\telse\n\t\t\t\t\tCWACStopRetransmission(WTPIndex);\n\t\t\t}\n\n\t\t\tCWDebugLog(\"Send a Station Configuration Request\");\n\t\t} else if (msgPtr->data_msgType == CW_DATA_MSG_KEEP_ALIVE_TYPE) {\n\n\t\t\tunsigned char *valPtr = NULL;\n\t\t\tCWProtocolMessage *messages = NULL;\n\t\t\tCWProtocolMessage sessionIDmsgElem;\n\t\t\tint fragmentsNum = 0;\n\t\t\tint i;\n\t\t\tint dataSocket = 0;\n\t\t\tunsigned short int elemType = 0;\n\t\t\tunsigned short int elemLen = 0;\n\t\t\tCWNetworkLev4Address address;\n\n\t\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\t\t\tvalPtr = CWParseSessionID(msgPtr, elemLen);\n\t\t\tCWAssembleMsgElemSessionID(&sessionIDmsgElem, valPtr);\n\n\t\t\tif (!CWAssembleDataMessage(&messages,\n\t\t\t\t\t\t   &fragmentsNum,\n\t\t\t\t\t\t   gWTPs[WTPIndex].pathMTU,\n\t\t\t\t\t\t   &sessionIDmsgElem, NULL, CW_PACKET_PLAIN, 1)) {\n\t\t\t\tCWLog(\"Failure Assembling KeepAlive Request\");\n\t\t\t\tif (messages)\n\t\t\t\t\tfor (i = 0; i < fragmentsNum; i++) {\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t\t\t\t\t}\n\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\n\t\t\tfor (i = 0; i < gACSocket.count; i++) {\n\t\t\t\tif (gACSocket.interfaces[i].sock == gWTPs[WTPIndex].socket) {\n\t\t\t\t\tdataSocket = gACSocket.interfaces[i].dataSock;\n\t\t\t\t\tCW_COPY_NET_ADDR_PTR(&address, &(gWTPs[WTPIndex].dataAddress));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (dataSocket == 0) {\n\t\t\t\tCWLog(\"data socket of WTP %d isn't ready.\");\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\n\t\t\t/* Set port and address of data tunnel */\n\t\t\t//sock_set_port_cw((struct sockaddr *)&(address), htons(CW_DATA_PORT));\n\n\t\t\tfor (i = 0; i < fragmentsNum; i++) {\n\t\t\t\tif (!CWNetworkSendUnsafeUnconnected(dataSocket,\n\t\t\t\t\t\t\t\t    &(address), messages[i].msg, messages[i].offset)) {\n\t\t\t\t\tCWLog(\"Failure sending  KeepAlive Request\");\n\t\t\t\t\tint k;\n\t\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t\t\t\t\t}\n\t\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tint k;\n\t\t\tfor (k = 0; messages && k < fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(messages);\n\n\t\t} else if (msgPtr->data_msgType == CW_IEEE_802_3_FRAME_TYPE) {\n\n\t\t\tCWDebugLog(\"Write 802.3 data to TAP[%d], len:%d\", gWTPs[WTPIndex].tap_fd, msglen);\n\t\t\twrite(gWTPs[WTPIndex].tap_fd, msgPtr->msg, msglen);\n\n\t\t} else if (msgPtr->data_msgType == CW_IEEE_802_11_FRAME_TYPE) {\n\n\t\t\tstruct ieee80211_hdr *hdr;\n\t\t\tu16 fc;\n\t\t\thdr = (struct ieee80211_hdr *)msgPtr->msg;\n\t\t\tfc = le_to_host16(hdr->frame_control);\n\t\t\tCWDebugLog(\"Received 802.11 Frame type: %d\", WLAN_FC_GET_TYPE(fc));\n\t\t\tCWDebugLog(\"Received 802.11 Frame sybtype: %d\", WLAN_FC_GET_STYPE(fc));\n\n\t\t\tif (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT || isEAPOL_Frame(msgPtr->msg, msglen)) {\n\n\t\t\t\tCWACsend_data_to_hostapd(WTPIndex, msgPtr->msg, msglen);\n\n\t\t\t} else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {\n\n\t\t\t\tif (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_NULLFUNC || WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH || WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ASSOC_REQ) {\n\t\t\t\t\tCWACsend_data_to_hostapd(WTPIndex, msgPtr->msg, msglen);\n\t\t\t\t} else {\n\t\t\t\t\tCWDebugLog(\"Sending 802.11 frame subtype %d to TAP[%d]\", WLAN_FC_GET_STYPE(fc), gWTPs[WTPIndex].tap_fd);\n\t\t\t\t\tint write_bytes =\n\t\t\t\t\t    write(gWTPs[WTPIndex].tap_fd, msgPtr->msg + HLEN_80211,\n\t\t\t\t\t\t  msglen - HLEN_80211);\n\n\t\t\t\t\tif (write_bytes != (msglen - 24)) {\n\t\t\t\t\t\tCWLog(\"%02X %02X %02X %02X %02X %02X \", msgPtr->msg[0],\n\t\t\t\t\t\t      msgPtr->msg[1],\n\t\t\t\t\t\t      msgPtr->msg[2], msgPtr->msg[3], msgPtr->msg[4], msgPtr->msg[5]);\n\n\t\t\t\t\t\tCWLog(\"Error:. RecvByte:%d, write_Byte:%d \", msglen - 24, write_bytes);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t } else {\n\t\t\t\twrite(gWTPs[WTPIndex].tap_fd, msgPtr->msg + HLEN_80211, msglen - HLEN_80211);\n\t\t\t\tCWDebugLog(\"Control Frame !!!\\n\");\n\t\t\t}\n\t\t\t\n\n\t\t\t//flush_pcap(msgPtr->msg, msglen, \"cap_wtp_to_ac.txt\");\n\n\t\t} else {\n\t\t\tCWDebugLog(\"Manage special data packets with frequency\");\n\n\t\t\t/************************************************************\n\t\t\t * Update 2009:                                             *\n\t\t\t *              Manage special data packets with frequency  *\n\t\t\t *              statistics informations.                    *\n\t\t\t ************************************************************/\n\n\t\t\tif (msgPtr->data_msgType == CW_DATA_MSG_FREQ_STATS_TYPE) {\n\n\t\t\t\tint cells;\t/* How many cell are heard */\n\t\t\t\tint isAck;\n\t\t\t\tchar *freqPayload;\n\t\t\t\tint socketIndex, indexToSend = htonl(WTPIndex);\n\n\t\t\t\tint sizeofAckInfoUnit = CW_FREQ_ACK_SIZE;\n\t\t\t\tint sizeofFreqInfoUnit = CW_FREQ_CELL_INFO_PAYLOAD_SIZE;\n\t\t\t\tint sizeOfPayload = 0, payload_offset = 0;\n\n\t\t\t\t/*-----------------------------------------------------------------------------------------------\n\t\t\t\t *  Payload Management ( infos for frequency application) :\n\t\t\t\t *      Ack       Structure : |  WTPIndex  |   Ack Value  |\n\t\t\t\t *      Freq Info Structure : |  WTPIndex  |  Number of cells  |  Frequecies Info Payload |\n\t\t\t\t *-----------------------------------------------------------------------------------------------*/\n\n\t\t\t\tmemcpy(&isAck, msgPtr->msg, sizeof(int));\n\n\t\t\t\tisAck = ntohl(isAck);\n\n\t\t\t\tif (isAck == 0) {\t/* isnt an ack message */\n\t\t\t\t\tmemcpy(&cells, msgPtr->msg + sizeof(int), sizeof(int));\n\t\t\t\t\tcells = ntohl(cells);\n\t\t\t\t\tsizeOfPayload = (cells * sizeofFreqInfoUnit) + (2 * sizeof(int));\n\t\t\t\t} else {\n\t\t\t\t\tsizeOfPayload = sizeofAckInfoUnit;\n\t\t\t\t}\n\n\t\t\t\tif ((freqPayload = malloc(sizeOfPayload)) != NULL) {\n\n\t\t\t\t\tmemset(freqPayload, 0, sizeOfPayload);\n\t\t\t\t\tmemcpy(freqPayload, &indexToSend, sizeof(int));\n\t\t\t\t\tpayload_offset += sizeof(int);\n\n\t\t\t\t\tif (isAck == 0) {\n\t\t\t\t\t\tmemcpy(freqPayload + payload_offset, msgPtr->msg + sizeof(int),\n\t\t\t\t\t\t       sizeOfPayload - payload_offset);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmemcpy(freqPayload + payload_offset, msgPtr->msg + sizeof(int),\n\t\t\t\t\t\t       sizeOfPayload - payload_offset);\n\t\t\t\t\t}\n\n\t\t\t\t\tsocketIndex = gWTPs[WTPIndex].applicationIndex;\n\n\t\t\t\t\t/****************************************************\n\t\t\t\t\t *      Forward payload to correct application      *\n\t\t\t\t\t ****************************************************/\n\n\t\t\t\t\tif (!CWErr(CWThreadMutexLock(&appsManager.socketMutex[socketIndex]))) {\n\t\t\t\t\t\tCWLog(\"[ACrunState]:: Error locking socket Application Mutex\");\n\t\t\t\t\t\tfree(freqPayload);\n\t\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Writen(appsManager.appSocket[socketIndex], freqPayload, sizeOfPayload) < 0) {\n\t\t\t\t\t\tCWThreadMutexUnlock(&appsManager.socketMutex[socketIndex]);\n\t\t\t\t\t\tfree(freqPayload);\n\t\t\t\t\t\tCWLog(\"[ACrunState]:: Error writing Message To Application\");\n\t\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t\t}\n\n\t\t\t\t\tCWThreadMutexUnlock(&appsManager.socketMutex[socketIndex]);\n\t\t\t\t\tfree(freqPayload);\n\t\t\t\t} else\n\t\t\t\t\tCWLog(\"[ACrunState]:: Malloc error (payload to frequency application\");\n\t\t\t}\n\n\t\t\tif (msgPtr->data_msgType == CW_DATA_MSG_STATS_TYPE) {\n\t\t\t\tif (!UnixSocksArray[WTPIndex].data_stats_sock) {\n\t\t\t\t\t//Init Socket only the first time when the function is called\n\t\t\t\t\tif ((UnixSocksArray[WTPIndex].data_stats_sock =\n\t\t\t\t\t     socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {\n\t\t\t\t\t\tCWDebugLog(\"Error creating socket for data send\");\n\t\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t\t}\n\n\t\t\t\t\tmemset(&(UnixSocksArray[WTPIndex].clntaddr), (int)NULL,\n\t\t\t\t\t       sizeof(UnixSocksArray[WTPIndex].clntaddr));\n\t\t\t\t\tUnixSocksArray[WTPIndex].clntaddr.sun_family = AF_UNIX;\n\n\t\t\t\t\t//make unix socket client path name by index i\n\t\t\t\t\tsnprintf(string, sizeof(string), \"%d\", WTPIndex);\n\t\t\t\t\tstring[sizeof(string) - 1] = 0;\n\t\t\t\t\tstrcpy(socketctl_path_name, SOCKET_PATH_AC);\n\t\t\t\t\tstrcat(socketctl_path_name, string);\n\t\t\t\t\tstrcpy(UnixSocksArray[WTPIndex].clntaddr.sun_path, socketctl_path_name);\n\n\t\t\t\t\tunlink(socketctl_path_name);\n\n\t\t\t\t\tmemset(&(UnixSocksArray[WTPIndex].servaddr), (int)NULL,\n\t\t\t\t\t       sizeof(UnixSocksArray[WTPIndex].servaddr));\n\t\t\t\t\tUnixSocksArray[WTPIndex].servaddr.sun_family = AF_UNIX;\n\n\t\t\t\t\t//make unix socket server path name by index i\n\t\t\t\t\tstrcpy(socketserv_path_name, SOCKET_PATH_RECV_AGENT);\n\t\t\t\t\tstrcat(socketserv_path_name, string);\n\t\t\t\t\tstrcpy(UnixSocksArray[WTPIndex].servaddr.sun_path, socketserv_path_name);\n\t\t\t\t\tprintf(\"\\n%s\\t%s\", socketserv_path_name, socketctl_path_name);\n\t\t\t\t\tfflush(stdout);\n\t\t\t\t}\n\n\t\t\t\tint nbytes;\n\t\t\t\tint pDataLen = 656;\t//len of Monitoring Data\n\n\t\t\t\t//Send data stats from AC thread to monitor client over unix socket\n\t\t\t\tnbytes = sendto(UnixSocksArray[WTPIndex].data_stats_sock, msgPtr->msg, pDataLen, 0,\n\t\t\t\t\t\t(struct sockaddr *)&(UnixSocksArray[WTPIndex].servaddr),\n\t\t\t\t\t\tsizeof(UnixSocksArray[WTPIndex].servaddr));\n\t\t\t\tif (nbytes < 0) {\n\t\t\t\t\tCWDebugLog(\"Error sending data over socket\");\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\treturn CW_TRUE;\n\t}\n\n\tif (!(CWACParseGenericRunMessage(WTPIndex, msgPtr, &controlVal))) {\n\t\t/* Two possible errors: WRONG_ARG and INVALID_FORMAT\n\t\t * In the second case we have an unexpected response: ignore the\n\t\t * message and log the event.\n\t\t */\n\t\treturn CW_FALSE;\n\t}\n\n\tswitch (controlVal.messageTypeValue) {\n\tcase CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE:{\n\t\t\tCWProtocolResultCode resultCode;\n\t\t\t/*Update 2009:\n\t\t\t   Store Protocol specific response data */\n\t\t\tCWProtocolVendorSpecificValues *protocolValues = NULL;\n\n\t\t\tif (!\n\t\t\t    (CWParseConfigurationUpdateResponseMessage\n\t\t\t     (msgPtr, controlVal.msgElemsLen, &resultCode, &protocolValues)))\n\t\t\t\treturn CW_FALSE;\n\n\t\t\tCWACStopRetransmission(WTPIndex);\n\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tCWSaveConfigurationUpdateResponseMessage(resultCode, WTPIndex, protocolValues);\n\n\t\t\tif (gWTPs[WTPIndex].interfaceCommandProgress == CW_TRUE) {\n\n\t\t\t\tCWThreadMutexLock(&gWTPs[WTPIndex].interfaceMutex);\n\n\t\t\t\tgWTPs[WTPIndex].interfaceResult = 1;\n\t\t\t\tgWTPs[WTPIndex].interfaceCommandProgress = CW_FALSE;\n\t\t\t\tCWSignalThreadCondition(&gWTPs[WTPIndex].interfaceComplete);\n\n\t\t\t\tCWThreadMutexUnlock(&gWTPs[WTPIndex].interfaceMutex);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\tcase CW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_REQUEST:{\n\t\t\tCWProtocolChangeStateEventRequestValues *valuesPtr;\n\n\t\t\tif (!(CWParseChangeStateEventRequestMessage2(msgPtr, controlVal.msgElemsLen, &valuesPtr)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!(CWSaveChangeStateEventRequestMessage(valuesPtr, &(gWTPs[WTPIndex].WTPProtocolManager))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tif (!(CWAssembleChangeStateEventResponse(&messages,\n\t\t\t\t\t\t\t\t &messagesCount,\n\t\t\t\t\t\t\t\t gWTPs[WTPIndex].pathMTU, controlVal.seqNum)))\n\t\t\t\treturn CW_FALSE;\n\t\t\ttoSend = CW_TRUE;\n\t\t\tbreak;\n\t\t}\n\tcase CW_MSG_TYPE_VALUE_ECHO_REQUEST:{\n\t\t\tif (!(CWParseEchoRequestMessage(msgPtr, controlVal.msgElemsLen)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!(CWAssembleEchoResponse(&messages,\n\t\t\t\t\t\t     &messagesCount, gWTPs[WTPIndex].pathMTU, controlVal.seqNum)))\n\t\t\t\treturn CW_FALSE;\n\n\t\t\ttoSend = CW_TRUE;\n\t\t\tbreak;\n\t\t}\n\tcase CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE:{\n\t\t\tCWProtocolResultCode resultCode;\n\t\t\tif (!(CWParseStationConfigurationResponseMessage(msgPtr, controlVal.msgElemsLen, &resultCode)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tCWACStopRetransmission(WTPIndex);\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\t\t\t//CWSaveStationConfigurationResponseMessage(resultCode, WTPIndex);  <-- Must be Implemented ????\n\n\t\t\tbreak;\n\t\t}\n\tcase CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_RESPONSE:{\n\t\t\tCWProtocolResultCode resultCode;\n\t\t\tif (!(CWParseClearConfigurationResponseMessage(msgPtr, controlVal.msgElemsLen, &resultCode)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tCWACStopRetransmission(WTPIndex);\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (gWTPs[WTPIndex].interfaceCommandProgress == CW_TRUE) {\n\t\t\t\tCWThreadMutexLock(&gWTPs[WTPIndex].interfaceMutex);\n\n\t\t\t\tgWTPs[WTPIndex].interfaceResult = 1;\n\t\t\t\tgWTPs[WTPIndex].interfaceCommandProgress = CW_FALSE;\n\t\t\t\tCWSignalThreadCondition(&gWTPs[WTPIndex].interfaceComplete);\n\n\t\t\t\tCWThreadMutexUnlock(&gWTPs[WTPIndex].interfaceMutex);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\tcase CW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_RESPONSE:{\n\t\t\tCWProtocolResultCode resultCode;\n\t\t\tif (!(CWParseWLANConfigurationResponseMessage(msgPtr, controlVal.msgElemsLen, &resultCode)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tCWACStopRetransmission(WTPIndex);\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (gWTPs[WTPIndex].interfaceCommandProgress == CW_TRUE) {\n\t\t\t\tCWThreadMutexLock(&gWTPs[WTPIndex].interfaceMutex);\n\n\t\t\t\tgWTPs[WTPIndex].interfaceResult = 1;\n\t\t\t\tgWTPs[WTPIndex].interfaceCommandProgress = CW_FALSE;\n\t\t\t\tCWSignalThreadCondition(&gWTPs[WTPIndex].interfaceComplete);\n\n\t\t\t\tCWThreadMutexUnlock(&gWTPs[WTPIndex].interfaceMutex);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\tcase CW_MSG_TYPE_VALUE_DATA_TRANSFER_REQUEST:{\n\t\t\tCWProtocolWTPDataTransferRequestValues valuesPtr;\n\n\t\t\tif (!(CWParseWTPDataTransferRequestMessage(msgPtr, controlVal.msgElemsLen, &valuesPtr)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!\n\t\t\t    (CWAssembleWTPDataTransferResponse\n\t\t\t     (&messages, &messagesCount, gWTPs[WTPIndex].pathMTU, controlVal.seqNum)))\n\t\t\t\treturn CW_FALSE;\n\t\t\ttoSend = CW_TRUE;\n\t\t\tbreak;\n\t\t}\n\tcase CW_MSG_TYPE_VALUE_WTP_EVENT_REQUEST:{\n\t\t\tCWProtocolWTPEventRequestValues valuesPtr;\n\n\t\t\tif (!(CWParseWTPEventRequestMessage(msgPtr, controlVal.msgElemsLen, &valuesPtr)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tif (timerSet) {\n\t\t\t\tif (!CWRestartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!CWStartNeighborDeadTimer(WTPIndex)) {\n\t\t\t\t\tCWCloseThread();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!(CWSaveWTPEventRequestMessage(&valuesPtr, &(gWTPs[WTPIndex].WTPProtocolManager))))\n\t\t\t\treturn CW_FALSE;\n\n\t\t\tif (!(CWAssembleWTPEventResponse(&messages,\n\t\t\t\t\t\t\t &messagesCount, gWTPs[WTPIndex].pathMTU, controlVal.seqNum)))\n\t\t\t\treturn CW_FALSE;\n\n\t\t\ttoSend = CW_TRUE;\n\t\t\tbreak;\n\t\t}\n\tdefault:\n\t\t/*\n\t\t * We have an unexpected request and we have to send\n\t\t * a corresponding response containing a failure result code\n\t\t */\n\t\tCWDebugLog(\"--> Not valid Request in Run State... we send a failure Response\");\n\n\t\tif (!(CWAssembleUnrecognizedMessageResponse(&messages,\n\t\t\t\t\t\t\t    &messagesCount,\n\t\t\t\t\t\t\t    gWTPs[WTPIndex].pathMTU,\n\t\t\t\t\t\t\t    controlVal.seqNum, controlVal.messageTypeValue + 1)))\n\t\t\treturn CW_FALSE;\n\n\t\ttoSend = CW_TRUE;\n\t\t/*return CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message not valid in Run State\"); */\n\t}\n\tif (toSend) {\n\t\tint i;\n\n\t\tif (messages == NULL)\n\t\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t\tfor (i = 0; i < messagesCount; i++) {\n#ifdef CW_NO_DTLS\n\t\t\tif (!CWNetworkSendUnsafeUnconnected(gWTPs[WTPIndex].socket,\n\t\t\t\t\t\t\t    &gWTPs[WTPIndex].address,\n\t\t\t\t\t\t\t    messages[i].msg, messages[i].offset)) {\n#else\n\t\t\tif (!(CWSecuritySend(gWTPs[WTPIndex].session, messages[i].msg, messages[i].offset))) {\n#endif\n\t\t\t\tCWFreeMessageFragments(messages, messagesCount);\n\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t}\n\t\tCWFreeMessageFragments(messages, messagesCount);\n\t\tCW_FREE_OBJECT(messages);\n\t}\n\tgWTPs[WTPIndex].currentState = CW_ENTER_RUN;\n\tgWTPs[WTPIndex].subState = CW_WAITING_REQUEST;\n\n\treturn CW_TRUE;\n}\n\nCWBool CWACParseGenericRunMessage(int WTPIndex, CWProtocolMessage * msg, CWControlHeaderValues * controlVal)\n{\n\n\tif (msg == NULL || controlVal == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!(CWParseControlHeader(msg, controlVal)))\n\t\t/* will be handled by the caller */\n\t\treturn CW_FALSE;\n\n\t/* skip timestamp */\n\tcontrolVal->msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\t/* Check if it is a request */\n\tif (controlVal->messageTypeValue % 2 == 1) {\n\n\t\treturn CW_TRUE;\n\t}\n\n\tif ((gWTPs[WTPIndex].responseSeqNum != controlVal->seqNum) ||\n\t    (gWTPs[WTPIndex].responseType != controlVal->messageTypeValue)) {\n\n\t\tCWDebugLog(\"gWTPs: %d\\n\", gWTPs[WTPIndex].responseSeqNum);\n\t\tCWDebugLog(\"controlVal: %d\\n\", controlVal->seqNum);\n\t\tCWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Seq Num or Msg Type not valid!\");\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\n/*Update 2009:\n    Added vendValues to include a response payload (to pass response data)*/\nCWBool CWParseConfigurationUpdateResponseMessage(CWProtocolMessage * msgPtr,\n\t\t\t\t\t\t int len,\n\t\t\t\t\t\t CWProtocolResultCode * resultCode,\n\t\t\t\t\t\t CWProtocolVendorSpecificValues ** vendValues)\n{\n\n\tint offsetTillMessages;\n\n\tif (msgPtr == NULL || resultCode == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"Parsing Configuration Update Response...\");\n\n\t/* parse message elements */\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\t*resultCode = CWProtocolRetrieve32(msgPtr);\n\t\t\tbreak;\n\n\t\t\t/*Update 2009:\n\t\t\t   Added case to implement conf update response with payload */\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE_WITH_PAYLOAD:{\n\t\t\t\tint payloadSize = 0;\n\t\t\t\tCW_CREATE_OBJECT_ERR(*vendValues, CWProtocolVendorSpecificValues,\n\t\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\n\t\t\t\t*resultCode = CWProtocolRetrieve32(msgPtr);\n\n\t\t\t\tif (CWProtocolRetrieve16(msgPtr) != CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE)\n\t\t\t\t\t/*For now, we only have UCI payloads, so we will accept only vendor payloads for protocol data */\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t\t\t    \"Unrecognized Message Element in Configuration Update Response\");\n\n\t\t\t\t(*vendValues)->vendorPayloadType = CWProtocolRetrieve16(msgPtr);\n\n\t\t\t\tswitch ((*vendValues)->vendorPayloadType) {\n\t\t\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\t\t\t\tpayloadSize = CWProtocolRetrieve32(msgPtr);\n\t\t\t\t\tif (payloadSize != 0) {\n\t\t\t\t\t\t(*vendValues)->payload =\n\t\t\t\t\t\t    (void *)CWProtocolRetrieveStr(msgPtr, payloadSize);\n\t\t\t\t\t} else\n\t\t\t\t\t\t(*vendValues)->payload = NULL;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\t\t\t\tpayloadSize = CWProtocolRetrieve32(msgPtr);\n\n\t\t\t\t\tif (payloadSize <= 0) {\n\t\t\t\t\t\t/* Payload can't be zero here,\n\t\t\t\t\t\t * at least the message type must be specified */\n\t\t\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t\t\t\t    \"Unrecognized Message Element in Configuration Update Response\");\n\t\t\t\t\t}\n\t\t\t\t\t(*vendValues)->payload =\n\t\t\t\t\t    (void *)CWProtocolRetrieveRawBytes(msgPtr, payloadSize);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t\t\t    \"Unrecognized Message Element in Configuration Update Response\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t    \"Unrecognized Message Element in Configuration Update Response\");\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCWLog(\"Configuration Update Response Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseWLANConfigurationResponseMessage(CWProtocolMessage * msgPtr, int len, CWProtocolResultCode * resultCode)\n{\n\tint offsetTillMessages;\n\n\tif (msgPtr == NULL || resultCode == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"Parsing WLAN Configuration Response...\");\n\n\t// parse message elements\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\t*resultCode = CWProtocolRetrieve32(msgPtr);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t    \"Unrecognized Message Element in Configuration WLAN Response\");\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCWLog(\"WLAN Configuration Response Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseClearConfigurationResponseMessage(CWProtocolMessage * msgPtr, int len, CWProtocolResultCode * resultCode)\n{\n\tint offsetTillMessages;\n\n\tif (msgPtr == NULL || resultCode == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"Parsing Clear Configuration Response...\");\n\n\t// parse message elements\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\t*resultCode = CWProtocolRetrieve32(msgPtr);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t    \"Unrecognized Message Element in Configuration Update Response\");\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCWLog(\"Clear Configuration Response Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseStationConfigurationResponseMessage(CWProtocolMessage * msgPtr, int len,\n\t\t\t\t\t\t  CWProtocolResultCode * resultCode)\n{\n\tint offsetTillMessages;\n\n\tif (msgPtr == NULL || resultCode == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"Parsing Station Configuration Response...\");\n\n\t// parse message elements\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\t*resultCode = CWProtocolRetrieve32(msgPtr);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t    \"Unrecognized Message Element in Station Configuration Response\");\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCWLog(\"Station Configuration Response Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveConfigurationUpdateResponseMessage(CWProtocolResultCode resultCode,\n\t\t\t\t\t\tint WTPIndex, CWProtocolVendorSpecificValues * vendValues)\n{\n\tchar *wumPayloadBytes = NULL;\n\tint closeWTPManager = CW_FALSE;\n\n\tif (vendValues != NULL) {\n\t\tchar *responseBuffer;\n\t\tint socketIndex, payloadSize, headerSize, netWTPIndex, netresultCode, netpayloadSize;\n\n\t\t/********************************\n\t\t *Payload Management        *\n\t\t ********************************/\n\n\t\theaderSize = 3 * sizeof(int);\n\n\t\tswitch (vendValues->vendorPayloadType) {\n\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\t\tif (vendValues->payload != NULL)\n\t\t\t\tpayloadSize = strlen((char *)vendValues->payload);\n\t\t\telse\n\t\t\t\tpayloadSize = 0;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\t\twumPayloadBytes = vendValues->payload;\n\t\t\tpayloadSize = 1;\n\n\t\t\t/*\n\t\t\t * When dealing with WUM responses, the dafault size\n\t\t\t * is 1 bytes, which is used for the type.\n\t\t\t *\n\t\t\t * The only response message with a bigger payload is the\n\t\t\t * WTP_VERSION_RESPONSE (4 bytes), as it carries the WTP version\n\t\t\t * together with the response type.\n\t\t\t */\n\t\t\tif (wumPayloadBytes[0] == WTP_VERSION_RESPONSE)\n\t\t\t\tpayloadSize = 4;\n\n\t\t\t/*\n\t\t\t * If we received a positive WTP_COMMIT_ACK, we need to terminate\n\t\t\t * the WTP Manager Thread.\n\t\t\t */\n\t\t\tif (wumPayloadBytes[0] == WTP_COMMIT_ACK && resultCode == CW_PROTOCOL_SUCCESS)\n\t\t\t\tcloseWTPManager = CW_TRUE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tpayloadSize = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tif ((responseBuffer = malloc(headerSize + payloadSize)) != NULL) {\n\n\t\t\tnetWTPIndex = htonl(WTPIndex);\n\t\t\tmemcpy(responseBuffer, &netWTPIndex, sizeof(int));\n\n\t\t\tnetresultCode = htonl(resultCode);\n\t\t\tmemcpy(responseBuffer + sizeof(int), &netresultCode, sizeof(int));\n\n\t\t\tnetpayloadSize = htonl(payloadSize);\n\t\t\tmemcpy(responseBuffer + (2 * sizeof(int)), &netpayloadSize, sizeof(int));\n\n\t\t\tif (payloadSize > 0) {\n\t\t\t\tmemcpy(responseBuffer + headerSize, (char *)vendValues->payload, payloadSize);\n\t\t\t\tif (vendValues->vendorPayloadType == CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI)\n\t\t\t\t\t((char *)vendValues->payload)[payloadSize] = '\\0';\n\t\t\t}\n\n\t\t\tsocketIndex = gWTPs[WTPIndex].applicationIndex;\n\n\t\t\t/****************************************************\n\t\t\t     * Forward payload to correct application       *\n\t\t\t ****************************************************/\n\n\t\t\tif (!CWErr(CWThreadMutexLock(&appsManager.socketMutex[socketIndex]))) {\n\t\t\t\tCWLog(\"Error locking numSocketFree Mutex\");\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\n\t\t\tif (Writen(appsManager.appSocket[socketIndex], responseBuffer, headerSize + payloadSize) < 0) {\n\t\t\t\tCWThreadMutexUnlock(&appsManager.socketMutex[socketIndex]);\n\t\t\t\tCWLog(\"Error locking numSocketFree Mutex\");\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\n\t\t\tCWThreadMutexUnlock(&appsManager.socketMutex[socketIndex]);\n\n\t\t}\n\t\tCW_FREE_OBJECT(responseBuffer);\n\t\tCW_FREE_OBJECT(vendValues->payload);\n\t\tCW_FREE_OBJECT(vendValues);\n\n\t} else if (!CWBindingSaveConfigurationUpdateResponse(resultCode, WTPIndex)) {\n\n\t\treturn CW_FALSE;\n\t}\n\n\t/*\n\t * On a positive WTP_COMMIT_ACK, we need to close the WTP Manager.\n\t */\n\tif (closeWTPManager) {\n\t\tgWTPs[WTPIndex].isRequestClose = CW_TRUE;\n\t\tCWSignalThreadCondition(&gWTPs[WTPIndex].interfaceWait);\n\t}\n\n\tCWDebugLog(\"Configuration Update Response Saved\");\n\treturn CW_TRUE;\n}\n\nCWBool CWParseWTPDataTransferRequestMessage(CWProtocolMessage * msgPtr, int len,\n\t\t\t\t\t    CWProtocolWTPDataTransferRequestValues * valuesPtr)\n{\n\tint offsetTillMessages;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"\");\n\tCWLog(\"#________ WTP Data Transfer (Run) ________#\");\n\tCWLog(\"Parsing WTP Data Transfer Request...\");\n\n\t// parse message elements\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_DATA_TRANSFER_DATA_CW_TYPE:{\n\t\t\t\tif (!(CWParseMsgElemDataTransferData(msgPtr, elemLen, valuesPtr)))\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\tCWDebugLog(\"----- %s --------\\n\", valuesPtr->debug_info);\n\t\t\t\tbreak;\n\t\t\t}\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t    \"Unrecognized Message Element in WTP Data Transfer Request\");\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseWTPEventRequestMessage(CWProtocolMessage * msgPtr, int len, CWProtocolWTPEventRequestValues * valuesPtr)\n{\n\n\tint offsetTillMessages;\n\tint i = 0, k = 0;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t/*\n\t   CW_CREATE_OBJECT_ERR(valuesPtr, CWProtocolWTPEventRequestValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\t */\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"\");\n\tCWLog(\"#________ WTP Event (Run) ________#\");\n\tCWLog(\"Parsing WTP Event Request...\");\n\n\tvaluesPtr->errorReportCount = 0;\n\tvaluesPtr->errorReport = NULL;\n\tvaluesPtr->duplicateIPv4 = NULL;\n\tvaluesPtr->duplicateIPv6 = NULL;\n\tvaluesPtr->WTPOperationalStatisticsCount = 0;\n\tvaluesPtr->WTPOperationalStatistics = NULL;\n\tvaluesPtr->WTPRadioStatisticsCount = 0;\n\tvaluesPtr->WTPRadioStatistics = NULL;\n\tvaluesPtr->WTPRebootStatistics = NULL;\n\n\t/* parse message elements */\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_CW_TYPE:\n\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->errorReport,\n\t\t\t\t\t     CWDecryptErrorReportValues,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tif (!(CWParseMsgElemDecryptErrorReport(msgPtr, elemLen, valuesPtr->errorReport)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_DUPLICATE_IPV4_ADDRESS_CW_TYPE:\n\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->duplicateIPv4,\n\t\t\t\t\t     WTPDuplicateIPv4, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tCW_CREATE_ARRAY_ERR((valuesPtr->duplicateIPv4)->MACoffendingDevice_forIpv4,\n\t\t\t\t\t    6, unsigned char, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tif (!(CWParseMsgElemDuplicateIPv4Address(msgPtr, elemLen, valuesPtr->duplicateIPv4)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_DUPLICATE_IPV6_ADDRESS_CW_TYPE:\n\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->duplicateIPv6,\n\t\t\t\t\t     WTPDuplicateIPv6, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tCW_CREATE_ARRAY_ERR((valuesPtr->duplicateIPv6)->MACoffendingDevice_forIpv6,\n\t\t\t\t\t    6, unsigned char, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tif (!(CWParseMsgElemDuplicateIPv6Address(msgPtr, elemLen, valuesPtr->duplicateIPv6)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_OPERAT_STATISTICS_CW_TYPE:\n\t\t\tvaluesPtr->WTPOperationalStatisticsCount++;\n\t\t\tmsgPtr->offset += elemLen;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_RADIO_STATISTICS_CW_TYPE:\n\t\t\tvaluesPtr->WTPRadioStatisticsCount++;\n\t\t\tmsgPtr->offset += elemLen;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_REBOOT_STATISTICS_CW_TYPE:\n\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->WTPRebootStatistics,\n\t\t\t\t\t     WTPRebootStatisticsInfo, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tif (!(CWParseWTPRebootStatistics(msgPtr, elemLen, valuesPtr->WTPRebootStatistics)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t    \"Unrecognized Message Element in WTP Event Request\");\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCW_CREATE_ARRAY_ERR(valuesPtr->WTPOperationalStatistics,\n\t\t\t    valuesPtr->WTPOperationalStatisticsCount,\n\t\t\t    WTPOperationalStatisticsValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCW_CREATE_ARRAY_ERR(valuesPtr->WTPRadioStatistics,\n\t\t\t    valuesPtr->WTPRadioStatisticsCount,\n\t\t\t    WTPRadioStatisticsValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tmsgPtr->offset = offsetTillMessages;\n\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_WTP_OPERAT_STATISTICS_CW_TYPE:\n\t\t\tif (!(CWParseWTPOperationalStatistics(msgPtr,\n\t\t\t\t\t\t\t      elemLen, &(valuesPtr->WTPOperationalStatistics[k++]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_RADIO_STATISTICS_CW_TYPE:\n\t\t\tif (!(CWParseWTPRadioStatistics(msgPtr, elemLen, &(valuesPtr->WTPRadioStatistics[i++]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tmsgPtr->offset += elemLen;\n\t\t\tbreak;\n\t\t}\n\t}\n\tCWLog(\"WTP Event Request Parsed\");\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveWTPEventRequestMessage(CWProtocolWTPEventRequestValues * WTPEventRequest,\n\t\t\t\t    CWWTPProtocolManager * WTPProtocolManager)\n{\n\n\tif (WTPEventRequest == NULL || WTPProtocolManager == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (WTPEventRequest->WTPRebootStatistics) {\n\n\t\tCW_FREE_OBJECT(WTPProtocolManager->WTPRebootStatistics);\n\t\tWTPProtocolManager->WTPRebootStatistics = WTPEventRequest->WTPRebootStatistics;\n\t}\n\n\tif ((WTPEventRequest->WTPOperationalStatisticsCount) > 0) {\n\n\t\tint i, k;\n\n\t\tfor (i = 0; i < (WTPEventRequest->WTPOperationalStatisticsCount); i++) {\n\n\t\t\t//found = CW_FALSE;\n\t\t\tfor (k = 0; k < (WTPProtocolManager->radiosInfo).radioCount; k++) {\n\n\t\t\t\tif ((WTPProtocolManager->radiosInfo).radiosInfo[k].radioID ==\n\t\t\t\t    (WTPEventRequest->WTPOperationalStatistics[i]).radioID) {\n\n\t\t\t\t\t//found = CW_TRUE;\n\t\t\t\t\t(WTPProtocolManager->radiosInfo).radiosInfo[k].TxQueueLevel =\n\t\t\t\t\t    (WTPEventRequest->WTPOperationalStatistics[i]).TxQueueLevel;\n\t\t\t\t\t(WTPProtocolManager->radiosInfo).radiosInfo[k].wirelessLinkFramesPerSec =\n\t\t\t\t\t    (WTPEventRequest->WTPOperationalStatistics[i]).wirelessLinkFramesPerSec;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*if(!found)\n\t\t\t   {\n\t\t\t   for(k=0; k<(WTPProtocolManager->radiosInfo).radioCount; k++)\n\t\t\t   {\n\t\t\t   if((WTPProtocolManager->radiosInfo).radiosInfo[k].radioID == UNUSED_RADIO_ID);\n\t\t\t   {\n\t\t\t   (WTPProtocolManager->radiosInfo).radiosInfo[k].radioID = (WTPEventRequest->WTPOperationalStatistics[i]).radioID;\n\t\t\t   (WTPProtocolManager->radiosInfo).radiosInfo[k].TxQueueLevel = (WTPEventRequest->WTPOperationalStatistics[i]).TxQueueLevel;\n\t\t\t   (WTPProtocolManager->radiosInfo).radiosInfo[k].wirelessLinkFramesPerSec = (WTPEventRequest->WTPOperationalStatistics[i]).wirelessLinkFramesPerSec;\n\t\t\t   }\n\t\t\t   }\n\t\t\t   } */\n\t\t}\n\t}\n\n\tif ((WTPEventRequest->WTPRadioStatisticsCount) > 0) {\n\n\t\tint i, k;\n\n\t\tfor (i = 0; i < (WTPEventRequest->WTPRadioStatisticsCount); i++) {\n\t\t\t//found = CW_FALSE;\n\t\t\tfor (k = 0; k < (WTPProtocolManager->radiosInfo).radioCount; k++) {\n\n\t\t\t\tif ((WTPProtocolManager->radiosInfo).radiosInfo[k].radioID ==\n\t\t\t\t    (WTPEventRequest->WTPOperationalStatistics[i]).radioID) {\n\n\t\t\t\t\t//found = CW_TRUE;\n\t\t\t\t\t(WTPProtocolManager->radiosInfo).radiosInfo[k].statistics =\n\t\t\t\t\t    (WTPEventRequest->WTPRadioStatistics[i]).WTPRadioStatistics;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*if(!found)\n\t\t\t   {\n\t\t\t   for(k=0; k<(WTPProtocolManager->radiosInfo).radioCount; k++)\n\t\t\t   {\n\t\t\t   if((WTPProtocolManager->radiosInfo).radiosInfo[k].radioID == UNUSED_RADIO_ID);\n\t\t\t   {\n\t\t\t   (WTPProtocolManager->radiosInfo).radiosInfo[k].radioID = (WTPEventRequest->WTPOperationalStatistics[i]).radioID;\n\t\t\t   (WTPProtocolManager->radiosInfo).radiosInfo[k].statistics = (WTPEventRequest->WTPRadioStatistics[i]).WTPRadioStatistics;\n\t\t\t   }\n\t\t\t   }\n\t\t\t   } */\n\t\t}\n\t}\n\t/*\n\t   CW_FREE_OBJECT((WTPEventRequest->WTPOperationalStatistics), (WTPEventRequest->WTPOperationalStatisticsCount));\n\t   CW_FREE_OBJECTS_ARRAY((WTPEventRequest->WTPRadioStatistics), (WTPEventRequest->WTPRadioStatisticsCount));\n\t   Da controllare!!!!!!!\n\t */\n\tCW_FREE_OBJECT(WTPEventRequest->WTPOperationalStatistics);\n\tCW_FREE_OBJECT(WTPEventRequest->WTPRadioStatistics);\n\t/*CW_FREE_OBJECT(WTPEventRequest); */\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleWTPDataTransferResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum)\n{\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 0;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling WTP Data Transfer Response...\");\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_DATA_TRANSFER_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"WTP Data Transfer Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleWTPEventResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 0;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling WTP Event Response...\");\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_WTP_EVENT_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"WTP Event Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseChangeStateEventRequestMessage2(CWProtocolMessage * msgPtr,\n\t\t\t\t\t      int len, CWProtocolChangeStateEventRequestValues ** valuesPtr)\n{\n\n\tint offsetTillMessages;\n\tint i = 0;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_OBJECT_ERR(*valuesPtr,\n\t\t\t     CWProtocolChangeStateEventRequestValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"\");\n\tCWLog(\"#________ WTP Change State Event (Run) ________#\");\n\n\t(*valuesPtr)->radioOperationalInfo.radiosCount = 0;\n\t(*valuesPtr)->radioOperationalInfo.radios = NULL;\n\n\t/* parse message elements */\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\t\tunsigned short int elemType = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int elemLen = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\t/*CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen); */\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE:\n\t\t\t/* just count how many radios we have, so we\n\t\t\t * can allocate the array\n\t\t\t */\n\t\t\t((*valuesPtr)->radioOperationalInfo.radiosCount)++;\n\t\t\tmsgPtr->offset += elemLen;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\tif (!(CWParseResultCode(msgPtr, elemLen, &((*valuesPtr)->resultCode))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t\t    \"Unrecognized Message Element in Change State Event Request\");\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCW_CREATE_ARRAY_ERR((*valuesPtr)->radioOperationalInfo.radios,\n\t\t\t    (*valuesPtr)->radioOperationalInfo.radiosCount,\n\t\t\t    CWRadioOperationalInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tmsgPtr->offset = offsetTillMessages;\n\n\ti = 0;\n\n\twhile (msgPtr->offset - offsetTillMessages < len) {\n\t\tunsigned short int type = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int len = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(msgPtr, &type, &len);\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!\n\t\t\t    (CWParseWTPRadioOperationalState\n\t\t\t     (msgPtr, len, &((*valuesPtr)->radioOperationalInfo.radios[i]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\ti++;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tmsgPtr->offset += len;\n\t\t\tbreak;\n\t\t}\n\t}\n\tCWLog(\"Change State Event Request Parsed\");\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveChangeStateEventRequestMessage(CWProtocolChangeStateEventRequestValues * valuesPtr,\n\t\t\t\t\t    CWWTPProtocolManager * WTPProtocolManager)\n{\n\n\tCWBool found;\n\tCWBool retValue = CW_TRUE;\n\n\tif (valuesPtr == NULL || WTPProtocolManager == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((valuesPtr->radioOperationalInfo.radiosCount) > 0) {\n\n\t\tint i, k;\n\t\tfor (i = 0; i < (valuesPtr->radioOperationalInfo.radiosCount); i++) {\n\n\t\t\tfound = CW_FALSE;\n\t\t\tfor (k = 0; k < (WTPProtocolManager->radiosInfo).radioCount; k++) {\n\n\t\t\t\tif ((WTPProtocolManager->radiosInfo).radiosInfo[k].radioID ==\n\t\t\t\t    (valuesPtr->radioOperationalInfo.radios[i]).ID) {\n\n\t\t\t\t\tfound = CW_TRUE;\n\t\t\t\t\t(WTPProtocolManager->radiosInfo).radiosInfo[k].operationalState =\n\t\t\t\t\t    (valuesPtr->radioOperationalInfo.radios[i]).state;\n\t\t\t\t\t(WTPProtocolManager->radiosInfo).radiosInfo[k].operationalCause =\n\t\t\t\t\t    (valuesPtr->radioOperationalInfo.radios[i]).cause;\n\t\t\t\t}\n\t\t\t\tif (!found)\n\t\t\t\t\tretValue = CW_FALSE;\n\t\t\t}\n\t\t}\n\t}\n\n\tCW_FREE_OBJECT(valuesPtr->radioOperationalInfo.radios)\n\t    CW_FREE_OBJECT(valuesPtr);\n\n\treturn retValue;\n}\n\nCWBool CWParseEchoRequestMessage(CWProtocolMessage * msgPtr, int len)\n{\n\n\tint offsetTillMessages;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif ((msgPtr->msg) == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\toffsetTillMessages = msgPtr->offset;\n\n\tCWLog(\"\");\n\tCWLog(\"#________ Echo Request (Run) ________#\");\n\n\t/* parse message elements */\n\twhile ((msgPtr->offset - offsetTillMessages) < len) {\n\t\tunsigned short int elemType = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int elemLen = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(msgPtr, &elemType, &elemLen);\n\n\t\t/*CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen); */\n\n\t\tswitch (elemType) {\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Echo Request must carry no message elements\");\n\t\t}\n\t}\n\n\tif ((msgPtr->offset - offsetTillMessages) != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCWLog(\"Echo Request Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleEchoResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 0;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Echo Response...\");\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_ECHO_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"Echo Response Assembled\");\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleConfigurationUpdateRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t    int *fragmentsNumPtr, int PMTU, int seqNum, int msgElement)\n{\n\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Configuration Update Request...\");\n\n\tswitch (msgElement) {\n\tcase CONFIG_UPDATE_REQ_QOS_ELEMENT_TYPE:{\n\t\t\tif (!CWBindingAssembleConfigurationUpdateRequest\n\t\t\t    (&msgElemsBinding, &msgElemBindingCount, BINDING_MSG_ELEMENT_TYPE_WTP_QOS)) {\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\tcase CONFIG_UPDATE_REQ_OFDM_ELEMENT_TYPE:{\n\t\t\tif (!CWBindingAssembleConfigurationUpdateRequest\n\t\t\t    (&msgElemsBinding, &msgElemBindingCount, BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL)) {\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\tcase CONFIG_UPDATE_REQ_VENDOR_UCI_ELEMENT_TYPE:{\n\t\t\tCWLog(\"Assembling UCI Conf Update Request\");\n\t\t\tif (!CWProtocolAssembleConfigurationUpdateRequest\n\t\t\t    (&msgElems, &msgElemCount, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI)) {\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\tcase CONFIG_UPDATE_REQ_VENDOR_WUM_ELEMENT_TYPE:{\n\t\t\tCWLog(\"Assembling WUM Conf Update Request\");\n\t\t\tif (!CWProtocolAssembleConfigurationUpdateRequest\n\t\t\t    (&msgElems, &msgElemCount, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM)) {\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"Configuration Update Request Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleClearConfigurationRequest(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum)\n{\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Clear Configuration Request...\");\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"Clear Configuration Request Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleWLANConfigurationRequest(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum,\n\t\t\t\t\t  unsigned char *recv_packet, int Operation, int len_packet)\n{\n\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 1;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling WLAN 802.11 Configuration Request...\");\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t// Assemble Message Elements\n\n\tif (Operation == CW_MSG_ELEMENT_IEEE80211_ADD_WLAN_CW_TYPE) {\n\t\tif (!(CWAssembleMsgElemAddWLAN(0, &(msgElems[++k]), recv_packet, len_packet))) {\t//radioID = 0 -valore predefinito-\n\n\t\t\tCWErrorHandleLast();\n\t\t\tint i;\n\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\n\t} else if (Operation == CW_MSG_ELEMENT_IEEE80211_DELETE_WLAN_CW_TYPE) {\n\n\t\tif (!(CWAssembleMsgElemDeleteWLAN(0, &(msgElems[++k]), recv_packet, len_packet))) {\t//radioID = 0 -valore predefinito-\n\t\t\tCWErrorHandleLast();\n\t\t\tint i;\n\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\t}\n\n\t/*  to be implemented in a case of Binding with appropriate messages elements -- see draft capwap-spec && capwap-binding\n\t   if(!CWBindingAssembleConfigurationUpdateRequest(&msgElemsBinding, &msgElemBindingCount)){\n\t   return CW_FALSE;\n\t   }\n\t */\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"Station WLAN 802.11 Configuration Request Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleStationConfigurationRequest(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU,\n\t\t\t\t\t     int seqNum, unsigned char *StationMacAddr, int Operation)\n{\n\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 1;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Station Configuration Request...\");\n        CWLog(\"StationMacAddr = %02X %02X %02X %02X %02X %02X\", StationMacAddr[0], StationMacAddr[1], StationMacAddr[2], StationMacAddr[3], StationMacAddr[4], StationMacAddr[5]);\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t// Assemble Message Elements\n\tif (Operation == CW_MSG_ELEMENT_ADD_STATION_CW_TYPE) {\n\t\tif (!(CWAssembleMsgElemAddStation(0, &(msgElems[++k]), StationMacAddr))) {\t//radioID = 0 -valore predefinito-\n\t\t\tCWErrorHandleLast();\n\t\t\tint i;\n\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\n\t} else if (Operation == CW_MSG_ELEMENT_DELETE_STATION_CW_TYPE) {\n\t\tif (!(CWAssembleMsgElemDeleteStation(0, &(msgElems[++k]), StationMacAddr))) {\t//radioID = 0 -valore predefinito-\n\t\t\tCWErrorHandleLast();\n\t\t\tint i;\n\t\t\tfor (i = 0; i <= k; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t\t}\n\t}\n\n\t/*  to be implemented in a case of Binding with appropriate messages elements -- see draft capwap-spec && capwap-binding\n\t   if(!CWBindingAssembleConfigurationUpdateRequest(&msgElemsBinding, &msgElemBindingCount)){\n\t   return CW_FALSE;\n\t   }\n\t */\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_STATION_CONFIGURATION_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"Station Configuration Request Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWStartNeighborDeadTimer(int WTPIndex)\n{\n\n\t/* start NeighborDeadInterval timer */\n\tif (!CWErr(CWTimerRequest(gCWNeighborDeadInterval,\n\t\t\t\t  &(gWTPs[WTPIndex].thread),\n\t\t\t\t  &(gWTPs[WTPIndex].currentTimer), CW_CRITICAL_TIMER_EXPIRED_SIGNAL))) {\n\t\treturn CW_FALSE;\n\t}\n\treturn CW_TRUE;\n}\n\nCWBool CWStartNeighborDeadTimerForEcho(int WTPIndex)\n{\n\n\tint echoInterval;\n\n\t/* start NeighborDeadInterval timer */\n\tCWACGetEchoRequestTimer(&echoInterval);\n\tif (!CWErr(CWTimerRequest(echoInterval,\n\t\t\t\t  &(gWTPs[WTPIndex].thread),\n\t\t\t\t  &(gWTPs[WTPIndex].currentTimer), CW_CRITICAL_TIMER_EXPIRED_SIGNAL))) {\n\t\treturn CW_FALSE;\n\t}\n\treturn CW_TRUE;\n}\n\nCWBool CWStopNeighborDeadTimer(int WTPIndex)\n{\n\n\tif (!CWTimerCancel(&(gWTPs[WTPIndex].currentTimer))) {\n\n\t\treturn CW_FALSE;\n\t}\n\treturn CW_TRUE;\n}\n\nCWBool CWRestartNeighborDeadTimer(int WTPIndex)\n{\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\tif (!CWStopNeighborDeadTimer(WTPIndex))\n\t\treturn CW_FALSE;\n\tif (!CWStartNeighborDeadTimer(WTPIndex))\n\t\treturn CW_FALSE;\n\n\tCWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\tCWDebugLog(\"NeighborDeadTimer restarted\");\n\treturn CW_TRUE;\n}\n\nCWBool CWRestartNeighborDeadTimerForEcho(int WTPIndex)\n{\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\tif (!CWStopNeighborDeadTimer(WTPIndex))\n\t\treturn CW_FALSE;\n\tif (!CWStartNeighborDeadTimerForEcho(WTPIndex))\n\t\treturn CW_FALSE;\n\n\tCWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);\n\n\tCWDebugLog(\"NeighborDeadTimer restarted for Echo interval\");\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACSettingsFile.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define CW_SETTINGS_FILE    \"/etc/capwap/settings.ac.txt\"\n\n#define CWMIN_DEFAULT   3\n#define CWMAX_DEFAULT   10\n#define AIFS_DEFAULT    1\n\nFILE *gSettingsFile = NULL;\nWTPQosValues *gDefaultQosValues = NULL;\nint gHostapd_port;\nchar *gHostapd_unix_path;\n\nvoid CWExtractValue(char *start, char **startValue, char **endValue, int *offset)\n{\n\t*offset = strspn(start + 1, \" \\t\\n\\r\");\n\t*startValue = start + 1 + *offset;\n\n\t*offset = strcspn(*startValue, \" \\t\\n\\r\");\n\t*endValue = *startValue + *offset - 1;\n}\n\nCWBool CWParseSettingsFile()\n{\n\tchar *line = NULL;\n\n\tgSettingsFile = fopen(CW_SETTINGS_FILE, \"rb\");\n\tif (gSettingsFile == NULL) {\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\tCW_CREATE_ARRAY_ERR(gDefaultQosValues, NUM_QOS_PROFILES, WTPQosValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\twhile ((line = (char *)CWGetCommand(gSettingsFile)) != NULL) {\n\t\tchar *startTag = NULL;\n\t\tchar *endTag = NULL;\n\n\t\tif ((startTag = strchr(line, '<')) == NULL) {\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ((endTag = strchr(line, '>')) == NULL) {\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"CWMIN_VOICE\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMIN_DEFAULT;\n\t\t\tgDefaultQosValues[VOICE_QUEUE_INDEX].cwMin = value;\n\t\t\tCWDebugLog(\"CWMIN_VOICE: %d\", gDefaultQosValues[VOICE_QUEUE_INDEX].cwMin);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"CWMAX_VOICE\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMAX_DEFAULT;\n\t\t\tgDefaultQosValues[VOICE_QUEUE_INDEX].cwMax = value;\n\t\t\tCWDebugLog(\"CWMAX_VOICE: %d\", gDefaultQosValues[VOICE_QUEUE_INDEX].cwMax);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"AIFS_VOICE\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = AIFS_DEFAULT;\n\t\t\tgDefaultQosValues[VOICE_QUEUE_INDEX].AIFS = value;\n\t\t\tCWDebugLog(\"AIFS_VOICE: %d\", gDefaultQosValues[VOICE_QUEUE_INDEX].AIFS);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"CWMIN_VIDEO\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMIN_DEFAULT;\n\t\t\tgDefaultQosValues[VIDEO_QUEUE_INDEX].cwMin = value;\n\t\t\tCWDebugLog(\"CWMIN_VIDEO: %d\", gDefaultQosValues[VIDEO_QUEUE_INDEX].cwMin);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"CWMAX_VIDEO\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMAX_DEFAULT;\n\t\t\tgDefaultQosValues[VIDEO_QUEUE_INDEX].cwMax = value;\n\t\t\tCWDebugLog(\"CWMAX_VIDEO: %d\", gDefaultQosValues[VIDEO_QUEUE_INDEX].cwMax);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"AIFS_VIDEO\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = AIFS_DEFAULT;\n\t\t\tgDefaultQosValues[VIDEO_QUEUE_INDEX].AIFS = value;\n\t\t\tCWDebugLog(\"AIFS_VIDEO: %d\", gDefaultQosValues[VIDEO_QUEUE_INDEX].AIFS);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"CWMIN_BEST_EFFORT\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMIN_DEFAULT;\n\t\t\tgDefaultQosValues[BESTEFFORT_QUEUE_INDEX].cwMin = value;\n\t\t\tCWDebugLog(\"CWMIN_BEST_EFFORT: %d\", gDefaultQosValues[BESTEFFORT_QUEUE_INDEX].cwMin);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"CWMAX_BEST_EFFORT\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMAX_DEFAULT;\n\t\t\tgDefaultQosValues[BESTEFFORT_QUEUE_INDEX].cwMax = value;\n\t\t\tCWDebugLog(\"CWMAX_BEST_EFFORT: %d\", gDefaultQosValues[BESTEFFORT_QUEUE_INDEX].cwMax);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"AIFS_BEST_EFFORT\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = AIFS_DEFAULT;\n\t\t\tgDefaultQosValues[BESTEFFORT_QUEUE_INDEX].AIFS = value;\n\t\t\tCWDebugLog(\"AIFS_BEST_EFFORT: %d\", gDefaultQosValues[BESTEFFORT_QUEUE_INDEX].AIFS);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"CWMIN_BACKGROUND\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMIN_DEFAULT;\n\t\t\tgDefaultQosValues[BACKGROUND_QUEUE_INDEX].cwMin = value;\n\t\t\tCWDebugLog(\"CWMIN_BACKGROUND: %d\", gDefaultQosValues[BACKGROUND_QUEUE_INDEX].cwMin);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"CWMAX_BACKGROUND\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = CWMAX_DEFAULT;\n\t\t\tgDefaultQosValues[BACKGROUND_QUEUE_INDEX].cwMax = value;\n\t\t\tCWDebugLog(\"CWMAX_BACKGROUND: %d\", gDefaultQosValues[BACKGROUND_QUEUE_INDEX].cwMax);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"AIFS_BACKGROUND\", endTag - startTag - 1)) {\n\t\t\tint value = atoi(endTag + 1);\n\n\t\t\tif (value == 0)\n\t\t\t\tvalue = AIFS_DEFAULT;\n\t\t\tgDefaultQosValues[BACKGROUND_QUEUE_INDEX].AIFS = value;\n\t\t\tCWDebugLog(\"AIFS_BACKGROUND: %d\", gDefaultQosValues[BACKGROUND_QUEUE_INDEX].AIFS);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"AC_HOSTAPD_PORT\", endTag - startTag - 1)) {\n\n\t\t\tgHostapd_port = atoi(endTag + 1);\n\n\t\t\tCWDebugLog(\"Hostapd Port connection: %d\", gHostapd_port);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"AC_HOSTAPD_UNIX_PATH\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tCW_CREATE_STRING_ERR(gHostapd_unix_path, offset,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tstrncpy(gHostapd_unix_path, startValue, offset);\n\t\t\tgHostapd_unix_path[offset] = '\\0';\n\n\t\t\tCWDebugLog(\"Hostapd Unix Domain Path: %s\", gHostapd_unix_path);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\n\t\t}\n\t\tCW_FREE_OBJECT(line);\n\t}\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "ACipcHostapd.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Sotiraq Sima (Sotiraq.Sima@gmail.com)                                         *\n *                                                                                         *\n *******************************************************************************************/\n#include <netinet/in.h>\n#include \"ACipcHostapd.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define EXIT_FRAME_THREAD(sock) CWLog(\"ERROR Handling Frames: application will be closed!\"); close(sock); exit(1);\n\n//#define LOCALUDP\n//#define NETUDP\n//#define USEIPV6\n\nstruct client_hostapd {\n\tchar live;\n\tchar start_set_fase;\n\tint associated;\n\tint address_size;\n#if defined(LOCALUDP)\n\tstruct sockaddr_un client;\n#else\n#if defined(USEIPV6)\n\tstruct sockaddr_in6 client;\n#else\n\tstruct sockaddr_in client;\n#endif\n#endif\n\n};\n\nstruct client_hostapd ch[CW_MAX_WTP];\n\nchar connected = 0;\nint sock;\nextern int wtpInRunState;\n\nvoid CWACsend_data_to_hostapd(int WTPIndex, unsigned char *buf, int len)\n{\n\tCWDebugLog(\"CWACsend_data_to_hostapd() \");\n\t\n\tunsigned char tmp_buf[3000];\n\ttmp_buf[0] = DATE_TO_AC;\n\tmemcpy(tmp_buf + 1, buf, len);\n\n\tif (sendto(sock, tmp_buf, len + 1, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tperror(\"send\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_CLOSE(int WTPIndex, unsigned char *buf, int len)\n{\n\n\tbuf[0] = CLOSE;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_SET_WTPRINFO(int WTPIndex, char *buf, int len)\n{\n\n\tbuf[0] = SET_WTPRINFO;\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_SET_RATES(int WTPIndex, char *buf, int len)\n{\n\n\tbuf[0] = SET_RATES;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_SET_MDC(int WTPIndex, char *buf, int len)\n{\n\n\tbuf[0] = SET_MDC;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_SET_MAC(int WTPIndex, char *buf, int len)\n{\n\n\tbuf[0] = SET_MAC;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_GOLIVE(int WTPIndex)\n{\n\n\tchar buf[1];\n\n\tbuf[0] = GOLIVE;\n\n\tif (sendto(sock, buf, 1, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_HAVE_TO_WAIT(int WTPIndex)\n{\n\n\tchar buf[1];\n\n\tbuf[0] = HAVE_TO_WAIT;\n\n\tif (sendto(sock, buf, 1, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWACsend_command_to_hostapd_SEND_WLAN(int WTPIndex)\n{\n\n        char buf[1];\n\n        buf[0] = SEND_WLAN_TO_WTP;\n        if (sendto(sock, buf, 1, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size) < 0) {\n                CWDebugLog(\"Error to send command frame on socket\");\n                return;\n        }\n\n}\n\n#if defined(LOCALUDP)\nvoid send_close_cmd(struct sockaddr_un cli, int as)\n{\n#else\n#if defined(USEIPV6)\nvoid send_close_cmd(struct sockaddr_in6 cli, int as)\n{\n#else\nvoid send_close_cmd(struct sockaddr_in cli, int as)\n{\n#endif\n\n#endif\n\n\tunsigned char cmd[10];\n\tcmd[0] = CLOSE;\n\n\tif (sendto(sock, cmd, 1, 0, (struct sockaddr *)&cli, as) < 0) {\n\t\tperror(\"send close\");\n\t\treturn;\n\t}\n\n}\n\nint We_Radio_Information_WTP(int WTPIndex)\n{\n\tint i;\n\tint a = 0;\n\tint b = 0;\n\tint c = 0;\n\n\tif (gWTPs[WTPIndex].SuppRates[0] != 0)\n\t\tb = 1;\n\tif (gWTPs[WTPIndex].RadioInformationABGN != 0)\n\t\ta = 1;\n\n\tfor (i = 0; i < 6; i++)\n\t\tif (gWTPs[WTPIndex].MultiDomCapa[i] != 0)\n\t\t\tc = 1;\n\n\tif (a && b && c)\n\t\treturn 1;\n\telse\n\t\treturn 0;\n}\n\nint Exist_WTPs()\n{\n\tint i;\n\tfor (i = 0; i < CW_MAX_WTP; i++)\n\t\tif (gWTPs[i].isNotFree)\n\t\t\treturn 1;\n\treturn 0;\n}\n\nint GetWTP_not_associated_to_Hostapd()\n{\n\tint i;\n\tfor (i = 0; i < CW_MAX_WTP; i++) {\n\t\tif (gWTPs[i].isNotFree && ch[i].associated == 0)\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\nCW_THREAD_RETURN_TYPE CWACipc_with_ac_hostapd(void *arg)\n{\n\n\tint tmp_WTPIndex = -1;\n\n\tint len;\n\tint k;\n\n#if defined(LOCALUDP)\n\tstruct sockaddr_un server;\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tstruct sockaddr_in6 server;\n#else\n\tstruct sockaddr_in server;\n#endif\n#endif\n\n\tunsigned char buffer[2048];\n\tint connect_ret;\n\tchar cmd[10];\n\n\tCWProtocolMessage *frame = NULL;\n\tCWNetworkLev4Address address;\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n#if defined(LOCALUDP)\n\tsock = socket(AF_UNIX, SOCK_DGRAM, 0);\n\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tbzero(&server, sizeof(server));\n\tsock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);\n#else\n\tmemset(&server, 0, sizeof(server));\n\tif ((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)\n\tCWDebugLog(\"WTP ipc HOSTAPD: Error listen \");\n#endif\n\n#else\n#if defined(USEIPV6)\n\tbzero(&server, sizeof(server));\n\tsock = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);\n#else\n\tmemset(&server, 0, sizeof(server));\n\tsock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);\n#endif\n\n#endif\n\n\tif (sock < 0) {\n\t\tCWDebugLog(\"AC ipc HOSTAPD: Error creating socket\");\n\t\tEXIT_FRAME_THREAD(sock);\n\t}\n\n\tCWDebugLog(\"AC ipc HOSTAPD: Trying to connect to hostapd (AC)...\");\n\t\n#if defined(LOCALUDP)\n\tserver.sun_family = AF_UNIX;\n\tstrcpy(server.sun_path, gHostapd_unix_path);\n\tunlink(server.sun_path);\n\tconnect_ret = bind(sock, (struct sockaddr *)&server, strlen(server.sun_path) + sizeof(server.sun_family));\n\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tserver.sin6_family = AF_INET6;\n\tserver.sin6_port = gHostapd_port;\n\tserver.sin6_addr = in6addr_any;\n#else\n\tserver.sin_family = AF_INET;\n\tserver.sin_port = htons(gHostapd_port);\n\tserver.sin_addr.s_addr = htonl(INADDR_ANY);\n#endif\n\tif ((connect_ret = bind(sock, (struct sockaddr *)&server, sizeof(server)))==-1)\n\tCWDebugLog(\"WTP ipc HOSTAPD: Error listen \");\n\n#endif\n\n\tif (connect_ret == -1) {\n\t\tCWDebugLog(\"AC ipc HOSTAPD: Error connect to socket\");\n\t\tEXIT_FRAME_THREAD(sock);\n\t}\n#if defined(LOCALUDP)\n\n#elif defined(NETUDP)\n\n#else\n\tif (listen(sock, CW_MAX_WTP) < 0) {\n\t\tCWDebugLog(\"AC ipc HOSTAPD: Error listen \");\n\t\tEXIT_FRAME_THREAD(sock);\n\t}\n#endif\n\n\tint i = 0;\n\tCWProtocolMessage *completeMsgPtr = NULL;\n\tint fragmentsNum = 0;\n\tCWMultiHomedSocket *sockPtr = &gACSocket;\n\tint dataSocket = 0;\n\n#if defined(LOCALUDP)\n\tstruct sockaddr_un client_tmp;\n\tclient_tmp.sun_family = AF_UNIX;\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tstruct sockaddr_in6 client_tmp;\n#else\n\tstruct sockaddr_in client_tmp;\n#endif\n#endif\n\n\tsocklen_t address_size_tmp = sizeof(client_tmp);\n\n\tfor (i = 0; i < CW_MAX_WTP; i++) {\n\t\tch[i].associated = 0;\n#if defined(LOCALUDP)\n\t\tch[i].client.sun_family = AF_UNIX;\n\t\tch[i].address_size = sizeof(struct sockaddr_un);\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\t\tch[i].client.sin6_port = 0;\n#else\n\t\tch[i].client.sin_port = 0;\n#endif\n#endif\n\n\t}\n\n#if defined(LOCALUDP)\n\tCWLog(\"Accept Packet at pipe: %s\", gHostapd_unix_path);\n\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tCWLog(\"Accept UDP v6 Packet at Port: %d\", server.sin6_port);\n#else\n\tCWLog(\"Accept UDP v4 Packet at Port: %d\", server.sin_port);\n#endif\n\n#else\n#if defined(USEIPV6)\n\tCWLog(\"Accept SCTP v6 Packet at Port: %d\", server.sin6_port);\n#else\n\tCWLog(\"Accept SCTP v4 Packet at Port: %d\", server.sin_port);\n#endif\n\n#endif\n\tCW_REPEAT_FOREVER {\n\n\t\ttmp_WTPIndex = -1;\n\t\tlen = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_tmp, &address_size_tmp);\n\n#if defined(LOCALUDP)\n\t\tsprintf(client_tmp.sun_path, \"%s%c%c%c%c%c\", server.sun_path, buffer[1], buffer[2], buffer[3],\n\t\t\tbuffer[4], buffer[5]);\n#endif\n\n\t\tif (Exist_WTPs() == 0) {\n\t\t\tsend_close_cmd(client_tmp, sizeof(client_tmp));\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (len <= 0) {\n\t\t\tcontinue;\t/* EXIT_FRAME_THREAD(sock) */\n\t\t}\n\n\t\tfor (i = 0; i < CW_MAX_WTP; i++) {\n\n#if defined(LOCALUDP)\n\t\t\tif (strcmp(client_tmp.sun_path, ch[i].client.sun_path) == 0) {\n\t\t\t\ttmp_WTPIndex = i;\n\t\t\t\tbreak;\n\t\t\t}\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\t\t\tif ((client_tmp.sin6_port == ch[i].client.sin6_port) &&\n\t\t\t    (strncmp(client_tmp.sin6_addr.s6_addr, ch[i].client.sin6_addr.s6_addr, 16) == 0)) {\n\t\t\t\ttmp_WTPIndex = i;\n\t\t\t}\n#else\n\t\t\tif ((client_tmp.sin_port == ch[i].client.sin_port) &&\n\t\t\t    (strcmp(inet_ntoa(client_tmp.sin_addr), inet_ntoa(ch[i].client.sin_addr)) == 0)) {\n\t\t\t\ttmp_WTPIndex = i;\n\t\t\t}\n#endif\n#endif\n\n\t\t}\n\n\t\tif (tmp_WTPIndex < 0) {\t// Client not recognized\n\n\t\t\tint wtp_non_associated = GetWTP_not_associated_to_Hostapd();\n\n\t\t\tif (wtp_non_associated >= 0) {\n\n\t\t\t\tif (buffer[0] == CONNECT) {\n\t\t\t\t\tch[wtp_non_associated].live = 0;\n\t\t\t\t\tch[wtp_non_associated].start_set_fase = 0;\n\t\t\t\t\tch[wtp_non_associated].associated = 1;\n\t\t\t\t\tch[wtp_non_associated].client = client_tmp;\n\t\t\t\t\tch[wtp_non_associated].address_size = address_size_tmp;\n\t\t\t\t\tcmd[0] = CONNECT_R;\n\t\t\t\t\tsendto(sock, cmd, 1, 0, (struct sockaddr *)&ch[wtp_non_associated].client,\n\t\t\t\t\t       ch[wtp_non_associated].address_size);\n\t\t\t\t\tCWLog(\"wtp_non_associated:%d\", wtp_non_associated);\n\n#if defined(LOCALUDP)\n\t\t\t\t\tCWLog(\"Hostapd_AC Connect: %s\", ch[wtp_non_associated].client.sun_path);\n#else\n#if defined(USEIPV6)\n\t\t\t\t\tCWLog(\"Hostapd_AC (v6) Connect: %d\", ch[wtp_non_associated].client.sin6_port);\n#else\n\t\t\t\t\tCWLog(\"Hostapd_AC (v4) Connect: %s:%d\",\n\t\t\t\t\t      inet_ntoa(ch[wtp_non_associated].client.sin_addr),\n\t\t\t\t\t      ch[wtp_non_associated].client.sin_port);\n#endif\n#endif\n\n\t\t\t\t\tcontinue;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tsend_close_cmd(client_tmp, sizeof(client_tmp));\n\t\t\t\t\tcontinue;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tsend_close_cmd(client_tmp, sizeof(client_tmp));\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t} else {\t// Client recognized\n\t\t\tint sig_byte = 1;\n\n#if defined(LOCALUDP)\n\t\t\tsig_byte = 6;\t//Code\n#endif\n\n\t\t\tif (buffer[0] == DATE_TO_WTP) {\n\n\t\t\t\tif (gWTPs[tmp_WTPIndex].currentState != CW_ENTER_RUN) {\n\t\t\t\t\tCWDebugLog(\"AC %d is not in RUN State. The packet was dropped.\", i);\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (len > (gWTPs[tmp_WTPIndex].pathMTU - 20)) {\n\t\t\t\t\tCWDebugLog(\"802.11 data length(%d) > MTU(%d)\", len,\n\t\t\t\t\t\t   gWTPs[tmp_WTPIndex].pathMTU);\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\n\t\t\t\t\tlen = len - sig_byte;\n\n\t\t\t\t\tCW_CREATE_OBJECT_ERR(frame, CWProtocolMessage, return 0;\n\t\t\t\t\t    );\n\t\t\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*frame, len, return 0;\n\t\t\t\t\t    );\n\n\t\t\t\t\tmemcpy(frame->msg, buffer + sig_byte, len);\n\n\t\t\t\t\tframe->offset = len;\n\t\t\t\t\tframe->data_msgType = CW_IEEE_802_11_FRAME_TYPE;\n\n\t\t\t\t\tif (!CWAssembleDataMessage\n\t\t\t\t\t    (&completeMsgPtr, &fragmentsNum, gWTPs[tmp_WTPIndex].pathMTU, frame, NULL,\n\t\t\t\t\t     CW_PACKET_PLAIN, 0)) {\n\t\t\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*frame);\n\t\t\t\t\t\tCW_FREE_OBJECT(frame);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (k = 0; k < sockPtr->count; k++) {\n\t\t\t\t\t\tif (sockPtr->interfaces[k].sock == gWTPs[tmp_WTPIndex].socket) {\n\t\t\t\t\t\t\tdataSocket = sockPtr->interfaces[k].dataSock;\n\t\t\t\t\t\t\tCW_COPY_NET_ADDR_PTR(&address, &(gWTPs[tmp_WTPIndex].dataAddress));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (dataSocket == 0) {\n\t\t\t\t\t\tCWDebugLog(\"data socket of WTP %d isn't ready.\");\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Set port and address of data tunnel */\n\t\t\t\t\t//sock_set_port_cw((struct sockaddr *)&(address), htons(CW_DATA_PORT));\n\t\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\t\tif (!CWNetworkSendUnsafeUnconnected\n\t\t\t\t\t\t    (dataSocket, &(address), completeMsgPtr[k].msg,\n\t\t\t\t\t\t     completeMsgPtr[k].offset)) {\n\t\t\t\t\t\t\tCWDebugLog(\"Failure sending Request\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t\t\t}\n\n\t\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*(frame));\n\t\t\t\t\tCW_FREE_OBJECT(frame);\n\t\t\t\t}\n\n\t\t\t} else if (buffer[0] == SET_ADDR) {\n\n\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\tif (CWAssembleStationConfigurationRequest(&(gWTPs[tmp_WTPIndex].messages),\n\t\t\t\t\t\t\t\t\t  &(gWTPs[tmp_WTPIndex].messagesCount),\n\t\t\t\t\t\t\t\t\t  gWTPs[tmp_WTPIndex].pathMTU,\n\t\t\t\t\t\t\t\t\t  seqNum, buffer + sig_byte,\n\t\t\t\t\t\t\t\t\t  CW_MSG_ELEMENT_ADD_STATION_CW_TYPE)) {\n\n\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t    (tmp_WTPIndex, CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE, seqNum))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\telse\n\t\t\t\t\t\tCWACStopRetransmission(tmp_WTPIndex);\n\n\t\t\t\t}\n\n\t\t\t} else if (buffer[0] == DEL_ADDR) {\n\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\tif (CWAssembleStationConfigurationRequest(&(gWTPs[tmp_WTPIndex].messages),\n\t\t\t\t\t\t\t\t\t  &(gWTPs[tmp_WTPIndex].messagesCount),\n\t\t\t\t\t\t\t\t\t  gWTPs[tmp_WTPIndex].pathMTU,\n\t\t\t\t\t\t\t\t\t  seqNum, buffer + sig_byte,\n\t\t\t\t\t\t\t\t\t  CW_MSG_ELEMENT_DELETE_STATION_CW_TYPE)) {\n\n\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t    (tmp_WTPIndex, CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE, seqNum))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\telse\n\t\t\t\t\t\tCWACStopRetransmission(tmp_WTPIndex);\n\t\t\t\t}\n\n\t\t\t} else if (buffer[0] == ADD_WLAN) {\n\t\t\t\tint seqNum = CWGetSeqNum();\n\n\t\t\t\t/* UP TAP Interface */\n\t\t\t\tchar str[100];\n\n\t\t\t\tsprintf(str, \"ifconfig %s down\", gWTPs[tmp_WTPIndex].tap_name);\n\t\t\t\tif (system(str)) {\n\t\t\t\t\tCWLog(\"Error: cmd: \\\"%s\\\" \", str);\n\t\t\t\t\tEXIT_FRAME_THREAD(sock);\n\t\t\t\t}\n\n\t\t\t\tsprintf(str, \"ifconfig %s hw ether %02X:%02X:%02X:%02X:%02X:%02X\\n\",\n\t\t\t\t\tgWTPs[tmp_WTPIndex].tap_name,\n\t\t\t\t\t(unsigned char)gWTPs[tmp_WTPIndex].RadioMAC[0],\n\t\t\t\t\t(unsigned char)gWTPs[tmp_WTPIndex].RadioMAC[1],\n\t\t\t\t\t(unsigned char)gWTPs[tmp_WTPIndex].RadioMAC[2],\n\t\t\t\t\t(unsigned char)gWTPs[tmp_WTPIndex].RadioMAC[3],\n\t\t\t\t\t(unsigned char)gWTPs[tmp_WTPIndex].RadioMAC[4],\n\t\t\t\t\t(unsigned char)gWTPs[tmp_WTPIndex].RadioMAC[5]);\n\n\t\t\t\tif (system(str)) {\n\t\t\t\t\tCWLog(\"Error: cmd: \\\"%s\\\" \", str);\n\t\t\t\t\tEXIT_FRAME_THREAD(sock);\n\t\t\t\t}\n\n\t\t\t\tsprintf(str, \"ifconfig %s up\", gWTPs[tmp_WTPIndex].tap_name);\n\n\t\t\t\tif (system(str)) {\n\t\t\t\t\tCWLog(\"Error: cmd: \\\"%s\\\" \", str);\n\t\t\t\t\tEXIT_FRAME_THREAD(sock);\n\t\t\t\t}\n\n\t\t\t\tif (CWAssembleWLANConfigurationRequest(&(gWTPs[tmp_WTPIndex].messages),\n\t\t\t\t\t\t\t\t       &(gWTPs[tmp_WTPIndex].messagesCount),\n\t\t\t\t\t\t\t\t       gWTPs[tmp_WTPIndex].pathMTU,\n\t\t\t\t\t\t\t\t       seqNum, buffer + sig_byte,\n\t\t\t\t\t\t\t\t       CW_MSG_ELEMENT_IEEE80211_ADD_WLAN_CW_TYPE,\n\t\t\t\t\t\t\t\t       len - sig_byte)) {\n\n\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t    (tmp_WTPIndex, CW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_RESPONSE, seqNum))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\telse\n\t\t\t\t\t\tCWACStopRetransmission(tmp_WTPIndex);\n\n\t\t\t\t}\n\n\t\t\t} else if (buffer[0] == DEL_WLAN) {\n\t\t\t\tint seqNum = CWGetSeqNum();\n\t\t\t\tif (CWAssembleWLANConfigurationRequest(&(gWTPs[tmp_WTPIndex].messages),\n\t\t\t\t\t\t\t\t       &(gWTPs[tmp_WTPIndex].messagesCount),\n\t\t\t\t\t\t\t\t       gWTPs[tmp_WTPIndex].pathMTU,\n\t\t\t\t\t\t\t\t       seqNum, buffer + sig_byte,\n\t\t\t\t\t\t\t\t       CW_MSG_ELEMENT_IEEE80211_DELETE_WLAN_CW_TYPE,\n\t\t\t\t\t\t\t\t       len - sig_byte)) {\n\n\t\t\t\t\tif (CWACSendAcknowledgedPacket\n\t\t\t\t\t    (tmp_WTPIndex, CW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_RESPONSE, seqNum))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\telse\n\t\t\t\t\t\tCWACStopRetransmission(tmp_WTPIndex);\n\n\t\t\t\t}\n\n\t\t\t} else if (buffer[0] == CLOSE) {\n\n#if defined(LOCALUDP)\n\t\t\t\tCWLog(\"Hostapd_AC Disconnect: %s\", ch[tmp_WTPIndex].client.sun_path);\n\t\t\t\tsprintf(ch[tmp_WTPIndex].client.sun_path, \"\");\n\n#else\n#if defined(USEIPV6)\n\t\t\t\tCWLog(\"Hostapd_AC (v6) Disconnect: %d\", ch[tmp_WTPIndex].client.sin6_port);\n\t\t\t\tch[tmp_WTPIndex].client.sin6_port = 0;\n#else\n\t\t\t\tCWLog(\"Hostapd_AC (v4) Disconnect: %s:%d\", inet_ntoa(ch[tmp_WTPIndex].client.sin_addr),\n\t\t\t\t      ch[tmp_WTPIndex].client.sin_port);\n\t\t\t\tch[tmp_WTPIndex].client.sin_port = 0;\n#endif\n#endif\n\t\t\t\tch[tmp_WTPIndex].live = 0;\n\t\t\t\tch[tmp_WTPIndex].start_set_fase = 1;\n\t\t\t\tch[tmp_WTPIndex].associated = 0;\n\n\t\t\t} else if (buffer[0] == WANT_GOLIVE) {\n\n\t\t\t\tif (ch[tmp_WTPIndex].start_set_fase) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (We_Radio_Information_WTP(tmp_WTPIndex) && ch[tmp_WTPIndex].live == 0) {\n\n\t\t\t\t\t/* NEXT STEP SET WTPRINFO */\n\t\t\t\t\tch[tmp_WTPIndex].start_set_fase = 1;\n\t\t\t\t\tchar tmp_RadioInfoABGN[2];\n\n\t\t\t\t\tCWThreadMutexLock(&gWTPsMutex);\n\t\t\t\t\ttmp_RadioInfoABGN[1] = gWTPs[tmp_WTPIndex].RadioInformationABGN;\n\t\t\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\t\t\t\t\tCWACsend_command_to_hostapd_SET_WTPRINFO(tmp_WTPIndex, tmp_RadioInfoABGN, 2);\n\n\t\t\t\t} else {\n\t\t\t\t\t/* NEXT STEP HAVE TO WAIT */\n\t\t\t\t\tCWACsend_command_to_hostapd_HAVE_TO_WAIT(tmp_WTPIndex);\n\t\t\t\t}\n\n\t\t\t} else if (buffer[0] == SET_WTPRINFO_R) {\n\n\t\t\t\t/* NEXT STEP SET RATES */\n\t\t\t\tchar tmp_SuppRates[9];\n\n\t\t\t\tCWThreadMutexLock(&gWTPsMutex);\n\t\t\t\tmemcpy(tmp_SuppRates + 1, gWTPs[tmp_WTPIndex].SuppRates, 8);\n\t\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\t\t\t\tCWACsend_command_to_hostapd_SET_RATES(tmp_WTPIndex, tmp_SuppRates, 9);\n\n\t\t\t} else if (buffer[0] == SET_RATES_R) {\n\n\t\t\t\t/* NEXT STEP  SET MDC */\n\t\t\t\tchar tmp_MultiDomCapa[7];\n\n\t\t\t\tCWThreadMutexLock(&gWTPsMutex);\n\t\t\t\tmemcpy(tmp_MultiDomCapa + 1, gWTPs[tmp_WTPIndex].MultiDomCapa, 6);\n\t\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\t\t\t\tCWACsend_command_to_hostapd_SET_MDC(tmp_WTPIndex, tmp_MultiDomCapa, 7);\n\n\t\t\t} else if (buffer[0] == SET_MDC_R) {\n\n\t\t\t\t/* NEXT STEP  SET MAC */\n\t\t\t\tchar tmp_mac[7];\n\n\t\t\t\tCWThreadMutexLock(&gWTPsMutex);\n\t\t\t\tmemcpy(tmp_mac + 1, gWTPs[tmp_WTPIndex].RadioMAC, 6);\n\t\t\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\t\t\t\tCWACsend_command_to_hostapd_SET_MAC(tmp_WTPIndex, tmp_mac, 7);\n\n\t\t\t} else if (buffer[0] == SET_MAC_R) {\n\n\t\t\t\t/* NEXT STEP  SET MDC */\n\t\t\t\tCWACsend_command_to_hostapd_GOLIVE(tmp_WTPIndex);\n\n\t\t\t} else if (buffer[0] == GOLIVE_R) {\n\t\t\t\tCWLog(\"GOLIVE_R from %d\", GOLIVE_R);\n\t\t\t\tch[GOLIVE_R].live = 1;\n\n\t\t\t} else {\n\t\t\t\tCWDebugLog(\"Received Unknow Command from Hostapd AC (%d)\", buffer[0]);\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tclose(sock);\n\treturn (NULL);\n}\n"
  },
  {
    "path": "ACipcHostapd.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Sotiraq Sima (Sotiraq.Sima@gmail.com)                                         *\n *                                                                                         *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_WTPFrameReceive_HEADER__\n#define __CAPWAP_WTPFrameReceive_HEADER__\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n\n#include \"smac_code.h\"\n#include \"CWAC.h\"\n\nvoid CWACsend_data_to_hostapd(int WTPIndex, unsigned char *buf, int len);\n\n#endif\n"
  },
  {
    "path": "COPYING",
    "content": "# *******************************************************************************************\n# * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n# *                      Universita' Campus BioMedico - Italy                               *\n# *                                                                                         *\n# * This program is free software; you can redistribute it and/or modify it under the terms *\n# * of the GNU General Public License as published by the Free Software Foundation; either  *\n# * version 2 of the License, or (at your option) any later version.                        *\n# *                                                                                         *\n# * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n# * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A \t    *\n# * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n# *                                                                                         *\n# * You should have received a copy of the GNU General Public License along with this       *\n# * program; if not, write to the:                                                          *\n# * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n# * MA  02111-1307, USA.                                                                    *\n# *                                                                                         *\n# * --------------------------------------------------------------------------------------- *\n# * Project:  Capwap                                                                        *\n# *                                                                                         *\n# * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *  \n# *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n# *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n# *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n# *\t      Donato Capitella (d.capitella@gmail.com)  \t                            *\n# *******************************************************************************************\n"
  },
  {
    "path": "CWAC.h",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Daniele De Sanctis (danieledesanctis@gmail.com)                                    *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#ifndef __CAPWAP_CWAC_HEADER__\n#define __CAPWAP_CWAC_HEADER__\n\n/*_______________________________________________________*/\n/*  *******************___INCLUDE___*******************  */\n#include \"CWCommon.h\"\n#include \"ACMultiHomedSocket.h\"\n#include \"ACProtocol.h\"\n#include \"ACInterface.h\"\n#include \"ACBinding.h\"\n\n#include <ctype.h>\n#include <netinet/in.h>\n#include <sys/un.h>\n#include <sys/socket.h>\n/*______________________________________________________*/\n/*  *******************___DEFINE___*******************  */\n#define CW_MAX_WTP              100\n#define CW_CRITICAL_TIMER_EXPIRED_SIGNAL    SIGUSR2\n#define CW_SOFT_TIMER_EXPIRED_SIGNAL        SIGUSR1\n#define AC_LOG_FILE_NAME                \"/var/log/ac.log.txt\"\n#define MAC_ADDR_LEN        6\n#define DEST_ADDR_START     4\n#define SOURCE_ADDR_START   10\n\n/*Definition of socket's path to send data stats */\n#define SOCKET_PATH_AC              \"/tmp/af_unix_ac_client\"\n#define SOCKET_PATH_RECV_AGENT          \"/tmp/monitorclt\"\n\n/*********************************************************\n * 2009 Updates:                                         *\n *              Message Element Types for the CWAsseble- *\n *              ConfigurationUpdateRequest Function.     *\n *********************************************************/\n\n#define CONFIG_UPDATE_REQ_QOS_ELEMENT_TYPE 0\n#define CONFIG_UPDATE_REQ_OFDM_ELEMENT_TYPE 1\n#define CONFIG_UPDATE_REQ_VENDOR_UCI_ELEMENT_TYPE 2\n#define CONFIG_UPDATE_REQ_VENDOR_WUM_ELEMENT_TYPE 3\n\n/********************************************************\n * 2009 Updates:                                        *\n * For manage the applications connected to AC we use   *\n * an array of socket. Through this array we can set    *\n * easily the correct answer socket.                    *\n * isFree and numSocketFree are used for management.    *\n * The mutex array is used for serialize the correct    *\n * write operation by the different wtp thread on the   *\n * relative application socket.                         *\n ********************************************************/\n\n#define MAX_APPS_CONNECTED_TO_AC 4\n\ntypedef struct {\n\tCWSocket appSocket[MAX_APPS_CONNECTED_TO_AC];\n\tCWBool isFree[MAX_APPS_CONNECTED_TO_AC];\n\tCWThreadMutex socketMutex[MAX_APPS_CONNECTED_TO_AC];\n\tint numSocketFree;\n\tCWThreadMutex numSocketFreeMutex;\n} applicationsManager;\n\napplicationsManager appsManager;\n\n/*_____________________________________________________*/\n/*  *******************___TYPES___*******************  */\n\n/*\n * Struct that describes a WTP from the AC's point of view\n */\ntypedef struct {\n\tCWNetworkLev4Address address;\n\tCWNetworkLev4Address dataAddress;\n\tCWThread thread;\n\tCWSecuritySession session;\n\tCWBool isNotFree;\n\tCWBool isRequestClose;\n\tCWStateTransition currentState;\n\tint interfaceIndex;\n\tCWSocket socket;\n\tunsigned char buf[CW_BUFFER_SIZE];\n\tenum {\n\t\tCW_DTLS_HANDSHAKE_IN_PROGRESS,\n\t\tCW_WAITING_REQUEST,\n\t\tCW_COMPLETED,\n\t} subState;\n\tCWSafeList packetReceiveList;\n\n\t/* depends on the current state: WaitJoin, NeighborDead */\n\tCWTimerID currentTimer;\n\tCWTimerID heartbeatTimer;\n\tCWList fragmentsList;\n\tint pathMTU;\n\n\t/**** ACInterface ****/\n\tint interfaceResult;\n\tCWBool interfaceCommandProgress;\n\tint interfaceCommand;\n\tCWThreadMutex interfaceSingleton;\n\tCWThreadMutex interfaceMutex;\n\tCWThreadCondition interfaceWait;\n\tCWThreadCondition interfaceComplete;\n\tWTPQosValues *qosValues;\n\t/********************************************************\n\t * 2009 Updates:                                        *\n\t * - ofdmValues is a struct for setting the values of   *\n\t *   a Configuration Update Request with message        *\n\t *   elemente OFDM.                                     *\n\t * - applicationIndex is the index of application which *\n\t *   request the command to WTP                         *\n\t *   (it will used for selecting the correct socket)    *\n\t ********************************************************/\n\n\tOFDMControlValues *ofdmValues;\n\tCWProtocolVendorSpecificValues *vendorValues;\n\tint applicationIndex;\n\n\t/**** ACInterface ****/\n\n\tCWWTPProtocolManager WTPProtocolManager;\n\n\t/* Retransmission */\n\tCWProtocolMessage *messages;\n\tint messagesCount;\n\tint retransmissionCount;\n\tCWTimerID currentPacketTimer;\n\tCWBool isRetransmitting;\n\n\t/* expected response */\n\tint responseType;\n\tint responseSeqNum;\n\n\t/* //Unrecognized message type value\n\t * int unrecognizedMsgType;\n\t */\n\t// TAP interface name\n\tchar tap_name[IFNAMSIZ];\n\tint tap_fd;\n\n\t// IEEE 802.11\n\tunsigned char RadioInformationABGN;\n\tunsigned char SuppRates[8];\n\tchar MultiDomCapa[6];\n\tunsigned char RadioMAC[6];\n\n} CWWTPManager;\n\n/*________________________________________________________________*/\n/*  *******************___EXTERN VARIABLES___*******************  */\nextern CWWTPManager gWTPs[CW_MAX_WTP];\nextern CWThreadMutex gWTPsMutex;\nextern CWSecurityContext gACSecurityContext;\nextern int gACHWVersion;\nextern int gACSWVersion;\nextern int gActiveStations;\nextern int gActiveWTPs;\nextern CWThreadMutex gActiveWTPsMutex;\nextern int gLimit;\nextern int gMaxWTPs;\nextern CWAuthSecurity gACDescriptorSecurity;\nextern int gRMACField;\nextern int gWirelessField;\nextern int gDTLSPolicy;\nextern CWThreadSpecific gIndexSpecific;\nextern char *gACName;\nextern int gDiscoveryTimer;\nextern int gEchoRequestTimer;\nextern int gIdleTimeout;\nextern CWProtocolNetworkInterface *gInterfaces;\nextern int gInterfacesCount;\nextern char **gMulticastGroups;\nextern int gMulticastGroupsCount;\nextern CWMultiHomedSocket gACSocket;\nextern WTPQosValues *gDefaultQosValues;\nextern int gHostapd_port;\nextern char *gHostapd_unix_path;\nextern unsigned char WTPRadioInformationType;\n\n/*________________________________________________________________*/\n\n/*  *******************___GLOBAL VARIABLES FOR ATH_MONITOR TEST___*******************  */\ntypedef struct {\n\tstruct sockaddr_un servaddr;\t/* address of Receive Agent */\n\tstruct sockaddr_un clntaddr;\t/* address on AC-side */\n\tint data_stats_sock;\n} UNIX_SOCKS_INFO;\n\nUNIX_SOCKS_INFO UnixSocksArray[CW_MAX_WTP];\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\n\n/* in AC.c */\nvoid CWACInit(void);\nvoid CWCreateConnectionWithHostapdAC(void);\nvoid CWACEnterMainLoop(void);\nCWBool CWACSendAcknowledgedPacket(int WTPIndex, int msgType, int seqNum);\nCWBool CWACResendAcknowledgedPacket(int WTPIndex);\nvoid CWACStopRetransmission(int WTPIndex);\nvoid CWACDestroy(void);\n\n/* in ACTest.h */\nCWBool ACQosTest(int WTPIndex);\n\n/* in ACRunState.c */\nCWBool CWSaveChangeStateEventRequestMessage(CWProtocolChangeStateEventRequestValues * valuesPtr,\n\t\t\t\t\t    CWWTPProtocolManager * WTPProtocolManager);\n\nCW_THREAD_RETURN_TYPE CWACipc_with_ac_hostapd(void *arg);\n//send_data_to_hostapd(unsigned char *, int);\n/****************************************************************\n * 2009 Updates:                                                *\n *              msgElement is used for differentiation between  *\n *              all message elements                            *\n ****************************************************************/\n\nCWBool CWAssembleConfigurationUpdateRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t    int *fragmentsNumPtr, int PMTU, int seqNum, int msgElement);\n\nCWBool CWAssembleStationConfigurationRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t     int *fragmentsNumPtr,\n\t\t\t\t\t     int PMTU, int seqNum, unsigned char *StationMacAddr, int Operation);\n\nCWBool CWAssembleClearConfigurationRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t   int *fragmentsNumPtr, int PMTU, int seqNum);\n\n/* in ACDiscoveryState.c */\nCWBool CWAssembleDiscoveryResponse(CWProtocolMessage ** messagesPtr, int seqNum);\nCWBool CWParseDiscoveryRequestMessage(unsigned char *msg, int len, int *seqNumPtr, CWDiscoveryRequestValues * valuesPtr);\n\n/* in ACRetransmission.c */\nCWBool CWACSendFragments(int WTPIndex);\n\n/* in ACRunStateCheck.c */\nCWBool CWACCheckForConfigurationUpdateRequest(int WTPIndex);\n\n/* in ACProtocol_User.c */\nCWBool CWACGetVendorInfos(CWACVendorInfos * valPtr);\nint CWACGetRMACField();\nint CWACGetWirelessField();\nint CWACGetDTLSPolicy();\nvoid CWACDestroyVendorInfos(CWACVendorInfos * valPtr);\n\n/* in ACMainLoop.c */\nvoid CWACManageIncomingPacket(CWSocket sock,\n\t\t\t      unsigned char *buf,\n\t\t\t      int len, int incomingInterfaceIndex, CWNetworkLev4Address * addrPtr, CWBool dataFlag);\n\nvoid *CWManageWTP(void *arg);\nvoid CWCloseThread();\n\n/* in CWSecurity.c */\nCWBool CWSecurityInitSessionServer(CWWTPManager * pWtp,\n\t\t\t\t   CWSocket sock, CWSecurityContext ctx, CWSecuritySession * sessionPtr, int *PMTUPtr);\n\nCWBool ACEnterJoin(int WTPIndex, CWProtocolMessage * msgPtr);\nCWBool ACEnterConfigure(int WTPIndex, CWProtocolMessage * msgPtr);\nCWBool ACEnterDataCheck(int WTPIndex, CWProtocolMessage * msgPtr);\nCWBool ACEnterRun(int WTPIndex, CWProtocolMessage * msgPtr, CWBool dataFlag);\n\nCW_THREAD_RETURN_TYPE CWInterface(void *arg);\n/* void CWTimerExpiredHandler(int arg); */\n#endif\n"
  },
  {
    "path": "CWBinding.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\nCWThreadMutex gWTPsMutex;\n\nconst int gMaxCAPWAPHeaderSizeBinding = 16;\t// note: this include optional Wireless field\n\nCWBool CWBindingCheckType(int elemType)\n{\n\tif (elemType >= BINDING_MIN_ELEM_TYPE && elemType <= BINDING_MAX_ELEM_TYPE)\n\t\treturn CW_TRUE;\n\treturn CW_FALSE;\n}\n\n// Assemble a CAPWAP Data Packet creating Transport Header.\n// completeMsgPtr is an array of fragments (can be of size 1 if the packet doesn't need fragmentation)\nCWBool CWAssembleDataMessage(CWProtocolMessage ** completeMsgPtr, int *fragmentsNumPtr, int PMTU,\n\t\t\t     CWProtocolMessage * frame, CWBindingTransportHeaderValues * bindingValuesPtr,\n\t\t\t     int is_crypted, int keepAlive)\n{\n\n\tCWProtocolMessage transportHdr;\n\tCWProtocolTransportHeaderValues transportVal;\n\n\tif (completeMsgPtr == NULL || fragmentsNumPtr == NULL || frame == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n//  CWDebugLog(\"PMTU: %d\", PMTU);\n\n\t// handle fragmentation\n\n\tPMTU = PMTU - gMaxCAPWAPHeaderSizeBinding;\n\n\tif (PMTU > 0) {\n\t\tPMTU = (PMTU / 8) * 8;\t// CAPWAP fragments are made of groups of 8 bytes\n\t\tif (PMTU == 0)\n\t\t\tgoto cw_dont_fragment;\n\n//      CWDebugLog(\"Aligned PMTU: %d\", PMTU);\n\t\t*fragmentsNumPtr = (frame->offset) / PMTU;\n\t\tif ((frame->offset % PMTU) != 0)\n\t\t\t(*fragmentsNumPtr)++;\n\t\t//CWDebugLog(\"Fragments #: %d\", *fragmentsNumPtr);\n\t} else {\n cw_dont_fragment:\n\t\t*fragmentsNumPtr = 1;\n\t}\n\n\ttransportVal.bindingValuesPtr = bindingValuesPtr;\n\n\tif (frame->data_msgType == CW_IEEE_802_11_FRAME_TYPE)\n\t\ttransportVal.type = 1;\n\n\tif (*fragmentsNumPtr == 1) {\n\n\t\ttransportVal.isFragment = transportVal.last = transportVal.fragmentOffset = transportVal.fragmentID = 0;\n\t\ttransportVal.payloadType = is_crypted;\n\n\t\t// Assemble Message Elements\n\n\t\tif (keepAlive) {\n\t\t\tif (!(CWAssembleTransportHeaderKeepAliveData(&transportHdr, &transportVal, keepAlive))) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t}\n\t\t} else {\n\n\t\t\tif (!(CWAssembleTransportHeader(&transportHdr, &transportVal))) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t}\n\t\t}\n\n\t\tCW_CREATE_OBJECT_ERR(*completeMsgPtr, CWProtocolMessage,\n\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tCW_CREATE_PROTOCOL_MESSAGE(((*completeMsgPtr)[0]), transportHdr.offset + frame->offset,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tCWProtocolStoreMessage(&((*completeMsgPtr)[0]), &transportHdr);\n\t\tCWProtocolStoreMessage(&((*completeMsgPtr)[0]), frame);\n\n\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t} else {\n\n\t\tint fragID = CWGetFragmentID();\n\t\tint totalSize = frame->offset;\n\n\t\t//CWDebugLog(\"%d Fragments\", *fragmentsNumPtr);\n\t\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(*completeMsgPtr, *fragmentsNumPtr,\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tframe->offset = 0;\n\n\t\tint i;\n\t\tfor (i = 0; i < *fragmentsNumPtr; i++) {\t// for each fragment to assemble\n\t\t\tint fragSize;\n\n\t\t\ttransportVal.isFragment = 1;\n\t\t\ttransportVal.fragmentOffset = (frame->offset) / 8;\n\t\t\ttransportVal.fragmentID = fragID;\n\t\t\ttransportVal.payloadType = is_crypted;\n\n\t\t\tif (i < ((*fragmentsNumPtr) - 1)) {\t// not last fragment\n\t\t\t\tfragSize = PMTU;\n\t\t\t\ttransportVal.last = 0;\n\t\t\t} else {\t// last fragment\n\t\t\t\tfragSize = totalSize - (((*fragmentsNumPtr) - 1) * PMTU);\n\t\t\t\ttransportVal.last = 1;\n\t\t\t}\n\n\t\t\tCWDebugLog(\"Fragment #:%d, offset:%d, bytes stored:%d/%d\", i, transportVal.fragmentOffset,\n\t\t\t\t   fragSize, totalSize);\n\n\t\t\t// Assemble Transport Header for this fragment\n\t\t\tif (keepAlive) {\n\t\t\t\tif (!(CWAssembleTransportHeaderKeepAliveData(&transportHdr, &transportVal, keepAlive))) {\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!(CWAssembleTransportHeader(&transportHdr, &transportVal))) {\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(((*completeMsgPtr)[i]), transportHdr.offset + fragSize,\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tCWProtocolStoreMessage(&((*completeMsgPtr)[i]), &transportHdr);\n\t\t\tCWProtocolStoreRawBytes(&((*completeMsgPtr)[i]), &((frame->msg)[frame->offset]), fragSize);\n\t\t\t(frame->offset) += fragSize;\n\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t}\n\t}\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleTransportHeaderBinding(CWProtocolMessage * transportHdrPtr, CWBindingTransportHeaderValues * valuesPtr)\n{\n\tint val = 0;\n\t/* Mauro: non piu' specificato nel campo Wireless Specific Information\n\t   CWSetField32(val,\n\t   CW_TRANSPORT_HEADER_WIRELESS_ID_START,\n\t   CW_TRANSPORT_HEADER_WIRELESS_ID_LEN,\n\t   CW_BINDING_WIRELESSID);\n\t */\n\tCWSetField32(val, CW_TRANSPORT_HEADER_LENGTH_START, CW_TRANSPORT_HEADER_LENGTH_LEN, CW_BINDING_DATALENGTH);\n\n//  CWDebugLog(\"#### RSSI in= %d\",valuesPtr->RSSI );\n\tCWSetField32(val, CW_TRANSPORT_HEADER_RSSI_START, CW_TRANSPORT_HEADER_RSSI_LEN, valuesPtr->RSSI);\n\n//  CWDebugLog(\"#### SNR in= %d\",valuesPtr->SNR );\n\tCWSetField32(val, CW_TRANSPORT_HEADER_SNR_START, CW_TRANSPORT_HEADER_SNR_LEN, valuesPtr->SNR);\n\n\t/* Mauro: inserisci il byte piu' significativo del sottocampo Data */\n\tCWSetField32(val,\n\t\t     CW_TRANSPORT_HEADER_DATARATE_1_START,\n\t\t     CW_TRANSPORT_HEADER_DATARATE_1_LEN, (valuesPtr->dataRate) >> 8);\n\n\tCWProtocolStore32(transportHdrPtr, val);\n\tval = 0;\n\n\t/* Mauro: inserisci il byte meno significativo del sottocampo Data */\n\tCWSetField32(val,\n\t\t     CW_TRANSPORT_HEADER_DATARATE_2_START,\n\t\t     CW_TRANSPORT_HEADER_DATARATE_2_LEN, (valuesPtr->dataRate) & 0x000000FF);\n\n//  CWDebugLog(\"#### data rate in= %d\",valuesPtr->dataRate );\n\t/*  CWSetField32(val,\n\t   CW_TRANSPORT_HEADER_DATARATE_START,\n\t   CW_TRANSPORT_HEADER_DATARATE_LEN,\n\t   valuesPtr->dataRate);\n\t */\n\tCWSetField32(val, CW_TRANSPORT_HEADER_PADDING_START, CW_TRANSPORT_HEADER_PADDING_LEN, 0);\n\n\tCWProtocolStore32(transportHdrPtr, val);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseTransportHeaderMACAddress(CWProtocolMessage * msgPtr, unsigned char *mac_ptr)\n{\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tunsigned char *vval;\n\tvval = malloc(7);\n\n\t//CWDebugLog(\"Parse Transport Header\");\n\tint Mac_len = CWProtocolRetrieve8(msgPtr);\n\n\tvval = (unsigned char *)CWProtocolRetrieveRawBytes(msgPtr, 7);\n\n\tif (mac_ptr != NULL) {\n\n\t\tCWThreadMutexLock(&gWTPsMutex);\n\t\tmemcpy(mac_ptr, vval, Mac_len);\n\t\tCWThreadMutexUnlock(&gWTPsMutex);\n\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseTransportHeaderBinding(CWProtocolMessage * msgPtr, CWBindingTransportHeaderValues * valuesPtr)\n{\n\tunsigned int val = 0;\n\n\tif (msgPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t//CWDebugLog(\"Parse Transport Header\");\n\tval = CWProtocolRetrieve32(msgPtr);\n\n\t/* Mauro: non piu' specificato nel campo Wireless Specific Information\n\t   if(CWGetField32(val, CW_TRANSPORT_HEADER_WIRELESS_ID_START, CW_TRANSPORT_HEADER_WIRELESS_ID_LEN) != CW_BINDING_WIRELESSID)\n\t   return CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Wrong Binding Wireless ID\");\n\t */\n\tif (CWGetField32(val, CW_TRANSPORT_HEADER_LENGTH_START, CW_TRANSPORT_HEADER_LENGTH_LEN) !=\n\t    CW_BINDING_DATALENGTH)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Wrong Binding Data Field Length\");\n\n\tvaluesPtr->RSSI = CWGetField32(val, CW_TRANSPORT_HEADER_RSSI_START, CW_TRANSPORT_HEADER_RSSI_LEN);\n//  CWDebugLog(\"RSSI: %d\", valuesPtr->RSSI);\n\n\tvaluesPtr->SNR = CWGetField32(val, CW_TRANSPORT_HEADER_SNR_START, CW_TRANSPORT_HEADER_SNR_LEN);\n//  CWDebugLog(\"SNR: %d\", valuesPtr->SNR);\n\n\t/* Mauro: preleva il byte piu' significativo del sottocampo Data */\n\tvaluesPtr->dataRate =\n\t    CWGetField32(val, CW_TRANSPORT_HEADER_DATARATE_1_START, CW_TRANSPORT_HEADER_DATARATE_1_LEN);\n\tval = CWProtocolRetrieve32(msgPtr);\n\n\t/* Daniele: controlla se si tratta di un msg dati(statistiche) o di un msg contenete un wireless frame */\n\n\t/************************************************************************\n\t * 2009 Update:                                                         *\n\t * For distinguish between the two types of \"specials\" data messages    *\n\t * (QoS stats and Frequency Stats) we used the following values:        *\n\t *      dataRate == 255 && SNR = 1 -> Frequency Stats Packet            *\n\t *      dataRate == 255            -> QoS Stats Packet                  *\n\t ************************************************************************/\n\n\tif (valuesPtr->dataRate == 255) {\n\t\tif (valuesPtr->SNR == 1)\n\t\t\tmsgPtr->data_msgType = CW_DATA_MSG_FREQ_STATS_TYPE;\n\t\telse\n\t\t\tmsgPtr->data_msgType = CW_DATA_MSG_STATS_TYPE;\n\t} else if (valuesPtr->dataRate == 0)\n\t\tmsgPtr->data_msgType = CW_DATA_MSG_FRAME_TYPE;\n\n\t/* Mauro: preleva il byte meno significativo del sottocampo Data */\n\tvaluesPtr->dataRate =\n\t    ((valuesPtr->dataRate) << 8) | CWGetField32(val, CW_TRANSPORT_HEADER_DATARATE_1_START,\n\t\t\t\t\t\t\tCW_TRANSPORT_HEADER_DATARATE_1_LEN);\n\n//  valuesPtr->dataRate = CWGetField32(val, CW_TRANSPORT_HEADER_DATARATE_START, CW_TRANSPORT_HEADER_DATARATE_LEN);\n//  CWDebugLog(\"DATARATE: %d\", valuesPtr->dataRate);\n\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "CWBinding.h",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Daniele De Sanctis (danieledesanctis@gmail.com)                                    *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#ifndef __CAPWAP_CWBinding_HEADER__\n#define __CAPWAP_CWBinding_HEADER__\n\n#define CW_BINDING_HLEN             4\n#define CW_BINDING_WIRELESSID           1\n#define CW_BINDING_DATALENGTH           4\n\n#define NUM_QOS_PROFILES            4\n#define UNUSED_QOS_VALUE            255\n\n#define VOICE_QUEUE_INDEX           0\n#define VIDEO_QUEUE_INDEX           1\n#define BESTEFFORT_QUEUE_INDEX          2\n#define BACKGROUND_QUEUE_INDEX          3\n\n#define BINDING_MIN_ELEM_TYPE           1024\n#define BINDING_MAX_ELEM_TYPE           2047\n\n#define UNUSED_OFDM_VALUE           255\n\n// Wireless ID viene preso dal campo WBID\n//#define CW_TRANSPORT_HEADER_WIRELESS_ID_START 0\n//#define CW_TRANSPORT_HEADER_WIRELESS_ID_LEN   8\n\n//#define CW_TRANSPORT_HEADER_LENGTH_START  8\n#define CW_TRANSPORT_HEADER_LENGTH_START    0\n#define CW_TRANSPORT_HEADER_LENGTH_LEN      8\n\n//#define CW_TRANSPORT_HEADER_RSSI_START        16\n#define CW_TRANSPORT_HEADER_RSSI_START      8\n#define CW_TRANSPORT_HEADER_RSSI_LEN        8\n\n//#define CW_TRANSPORT_HEADER_SNR_START     24\n#define CW_TRANSPORT_HEADER_SNR_START       16\n#define CW_TRANSPORT_HEADER_SNR_LEN     8\n\n// Poiche' nel draft 09 il campo del CAPWAP header Wireless Specific\n// Information e' stato privato del sottocampo Wireless ID con il\n// conseguente shift a sx di 8 bit dei sottocampi successivi il sottocampo\n// datarate del binding si trova a cavallo tra 2 word da 4 byte quindi\n// vanno specificati due offset.\n//#define CW_TRANSPORT_HEADER_DATARATE_START    0\n//#define CW_TRANSPORT_HEADER_DATARATE_LEN  16\n\n#define CW_TRANSPORT_HEADER_DATARATE_1_START    24\n#define CW_TRANSPORT_HEADER_DATARATE_1_LEN  8\n\n#define CW_TRANSPORT_HEADER_DATARATE_2_START    0\n#define CW_TRANSPORT_HEADER_DATARATE_2_LEN  8\n\n//#define CW_TRANSPORT_HEADER_PADDING_START 16\n//#define CW_TRANSPORT_HEADER_PADDING_LEN       16\n#define CW_TRANSPORT_HEADER_PADDING_START   8\n#define CW_TRANSPORT_HEADER_PADDING_LEN     24\n\n#define BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL   1033\n#define BINDING_MSG_ELEMENT_TYPE_WTP_QOS    1045\n\n/****************************************************\n * 2009 Update:                                     *\n *              Lengths Messages Element Definition *\n *              Specified in the 802.11 binding     *\n ****************************************************/\n\n#define BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL_LENGTH 8\n\n/****************************************************\n * 2009 Update:                                     *\n *              Define Structure for OFDM contol    *\n *              Values Management                   *\n ****************************************************/\n\ntypedef struct {\n\tint currentChan;\t/* 16 Bit Value */\n\tunsigned char BandSupport;\n\tunsigned int TIThreshold;\n} OFDMControlValues;\n\ntypedef struct {\n\tunsigned char queueDepth;\n\tint cwMin;\n\tint cwMax;\n\tunsigned char AIFS;\n\tunsigned char dot1PTag;\n\tunsigned char DSCPTag;\n} WTPQosValues;\n\ntypedef struct {\n\tWTPQosValues *qosValues;\n} bindingValues;\n\n/*---------------------------*/\n\ntypedef struct {\n\tchar RSSI;\n\tchar SNR;\n\tint dataRate;\n} CWBindingTransportHeaderValues;\n\ntypedef struct {\n\tCWProtocolMessage *frame;\n\tCWBindingTransportHeaderValues *bindingValues;\n} CWBindingDataListElement;\n\nextern const int gMaxCAPWAPHeaderSizeBinding;\n\nCWBool CWAssembleDataMessage(CWProtocolMessage ** completeMsgPtr, int *fragmentsNumPtr, int PMTU,\n\t\t\t     CWProtocolMessage * frame, CWBindingTransportHeaderValues * bindingValuesPtr,\n\t\t\t     int is_crypted, int keepAlive);\nCWBool CWAssembleTransportHeaderBinding(CWProtocolMessage * transportHdrPtr,\n\t\t\t\t\tCWBindingTransportHeaderValues * valuesPtr);\nCWBool CWBindingCheckType(int elemType);\nCWBool CWParseTransportHeaderBinding(CWProtocolMessage * msgPtr, CWBindingTransportHeaderValues * valuesPtr);\nCWBool CWParseTransportHeaderMACAddress(CWProtocolMessage * msgPtr,unsigned char *mac_ptr);\n\n#endif\n"
  },
  {
    "path": "CWCommon.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nint gCWForceMTU = 0;\nint gCWRetransmitTimer = CW_RETRANSMIT_INTERVAL_DEFAULT;\t//Default value for RetransmitInterval\nint gCWNeighborDeadInterval = CW_NEIGHBORDEAD_INTERVAL_DEFAULT;\t//Default value for NeighbourDeadInterval (no less than 2*EchoInterval and no greater than 240)\nint gCWMaxRetransmit = CW_MAX_RETRANSMIT_DEFAULT;\t//Default value for MaxRetransmit\n\nint CWTimevalSubtract(struct timeval *res, const struct timeval *x, const struct timeval *y)\n{\n\tint nsec;\n\tstruct timeval z = *y;\n\n\t// Perform the carry for the later subtraction by updating Y\n\tif (x->tv_usec < z.tv_usec) {\n\t\tnsec = (z.tv_usec - x->tv_usec) / 1000000 + 1;\n\t\tz.tv_usec -= 1000000 * nsec;\n\t\tz.tv_sec += nsec;\n\t}\n\tif (x->tv_usec - z.tv_usec > 1000000) {\n\t\tnsec = (x->tv_usec - z.tv_usec) / 1000000;\n\t\tz.tv_usec += 1000000 * nsec;\n\t\tz.tv_sec -= nsec;\n\t}\n\t// Compute the time remaining to wait. `tv_usec' is certainly positive\n\tif (res != NULL) {\n\t\tres->tv_sec = x->tv_sec - z.tv_sec;\n\t\tres->tv_usec = x->tv_usec - z.tv_usec;\n\t}\n\t// Return 1 if result is negative (x < y)\n\treturn ((x->tv_sec < z.tv_sec) || ((x->tv_sec == z.tv_sec) && (x->tv_usec < z.tv_usec)));\n}\n"
  },
  {
    "path": "CWCommon.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-9 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                     *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWCommon_HEADER__\n#define __CAPWAP_CWCommon_HEADER__\n\n#include <stdio.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <sys/time.h>\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <signal.h>\n#include <unistd.h>\n#ifdef MACOSX\n#include <netinet/if_ether.h>\n#else\n#include <linux/if_ether.h>\n#endif\n#include <net/if.h>\n#include <sys/ioctl.h>\n#include <sys/file.h>\n#include <sys/resource.h>\n#include \"wireless_copy.h\"\n\n// make sure the types really have the right sizes\n#define CW_COMPILE_TIME_ASSERT(name, x)               typedef int CWDummy_ ## name[(x) * 2 - 1]\n\n// if you get a compile error, change types (NOT VALUES!) according to your system\nCW_COMPILE_TIME_ASSERT(int_size, sizeof(int) == 4);\nCW_COMPILE_TIME_ASSERT(char_size, sizeof(char) == 1);\n\n#define     CW_BUFFER_SIZE                  65536\n#define     CW_ZERO_MEMORY                  bzero\n#define     CW_COPY_MEMORY(dst, src, len)           bcopy(src, dst, len)\n#define     CW_REPEAT_FOREVER               while(1)\n\n#define DEFAULT_LOG_SIZE                    1000000\n\ntypedef enum {\n\tCW_FALSE = 0,\n\tCW_TRUE = 1\n} CWBool;\n\ntypedef enum {\n\tCW_ENTER_SULKING,\n\tCW_ENTER_DISCOVERY,\n\tCW_ENTER_JOIN,\n\tCW_ENTER_CONFIGURE,\n\tCW_ENTER_DATA_CHECK,\n\tCW_ENTER_RUN,\n\tCW_ENTER_RESET,\n\tCW_QUIT\n} CWStateTransition;\n\nextern const char *CW_CONFIG_FILE;\nextern int gCWForceMTU;\nextern int gCWRetransmitTimer;\nextern int gCWNeighborDeadInterval;\nextern int gCWMaxRetransmit;\nextern int gMaxLogFileSize;\nextern int gEnabledLog;\nextern int gCWDiscoveryCount;\n\n#define CW_FREE_OBJECT(obj_name)        {if(obj_name){free((obj_name)); (obj_name) = NULL;}}\n#define CW_FREE_OBJECTS_ARRAY(ar_name, ar_size) {int _i = 0; for(_i = ((ar_size)-1); _i >= 0; _i--) {if(((ar_name)[_i]) != NULL){ free((ar_name)[_i]);}} free(ar_name); (ar_name) = NULL; }\n#define CW_PRINT_STRING_ARRAY(ar_name, ar_size) {int i = 0; for(i = 0; i < (ar_size); i++) printf(\"[%d]: **%s**\\n\", i, ar_name[i]);}\n\n// custom error\n#define CW_CREATE_OBJECT_ERR(obj_name, obj_type, on_err)    {obj_name = (obj_type*) (malloc(sizeof(obj_type))); if(!(obj_name)) {on_err}}\n#define CW_CREATE_OBJECT_SIZE_ERR(obj_name, obj_size,on_err)    {obj_name = (malloc(obj_size)); if(!(obj_name)) {on_err}}\n#define CW_CREATE_ARRAY_ERR(ar_name, ar_size, ar_type, on_err)  {ar_name = (ar_type*) (malloc(sizeof(ar_type) * (ar_size))); if(!(ar_name)) {on_err}}\n#define CW_CREATE_STRING_ERR(str_name, str_length, on_err)  {str_name = (char*) (malloc(sizeof(char) * ((str_length)+1) ) ); if(!(str_name)) {on_err}}\n#define CW_CREATE_STRING_FROM_STRING_ERR(str_name, str, on_err) {CW_CREATE_STRING_ERR(str_name, strlen(str), on_err); strcpy((str_name), str);}\n\n#ifdef CW_DEBUGGING\n\n#define CW_CREATE_ARRAY_ERR2(ar_name, ar_size, ar_type, on_err)     {ar_name = (ar_type*) (malloc(sizeof(ar_type) * (ar_size))); if((ar_name)) {on_err}}\n#define CW_CREATE_OBJECT_ERR2(obj_name, obj_type, on_err)       {obj_name = (obj_type*) (malloc(sizeof(obj_type))); if((obj_name)) {on_err}}\n#define CW_CREATE_OBJECT_SIZE_ERR2(obj_name, obj_size,on_err)       {obj_name = (malloc(obj_size)); if((obj_name)) {on_err}}\n#define CW_CREATE_STRING_ERR2(str_name, str_length, on_err)     {str_name = (char*) (malloc(sizeof(char) * ((str_length)+1) ) ); if((str_name)) {on_err}}\n#define CW_CREATE_STRING_FROM_STRING_ERR2(str_name, str, on_err)    {CW_CREATE_STRING_ERR2(str_name, strlen(str), on_err); strcpy((str_name), str);}\n\n#endif\n\n#include \"CWStevens.h\"\n#include \"config.h\"\n#include \"CWLog.h\"\n#include \"CWErrorHandling.h\"\n\n#include \"CWRandom.h\"\n//#include \"CWTimer.h\"\n#include \"timerlib.h\"\n#include \"CWThread.h\"\n#include \"CWNetwork.h\"\n#include \"CWList.h\"\n#include \"CWSafeList.h\"\n\n#include \"CWProtocol.h\"\n#include \"CWSecurity.h\"\n#include \"CWConfigFile.h\"\n\nint CWTimevalSubtract(struct timeval *res, const struct timeval *x, const struct timeval *y);\nCWBool CWParseSettingsFile();\nvoid CWErrorHandlingInitLib();\n\n#endif\n"
  },
  {
    "path": "CWConfigFile.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nFILE *gCWConfigFile = NULL;\n\nCWConfigValue *gConfigValues;\nint gConfigValuesCount;\n\n/*\n * Replacement for std fgets which seems to dislike windows return character\n */\nchar *CWFgets(char *buf, int bufSize, FILE * f)\n{\n\tint i = -1;\n\n\tif (buf == NULL || f == NULL || bufSize <= 0)\n\t\treturn NULL;\n\n\tCW_ZERO_MEMORY(buf, bufSize);\n\n\tdo {\n\t\ti++;\n\t\tbuf[i] = getc(f);\n\t\tif (buf[i] == EOF) {\n\t\t\ti--;\n\t\t\tbreak;\n\t\t}\n\t} while (i < bufSize && buf[i] != '\\n' && buf[i] != '\\r');\n\n\tif (i == -1)\n\t\treturn NULL;\n\ti++;\n\tbuf[i] = '\\0';\n\n\treturn buf;\n}\n\n/*\n * Get one \"useful\" (not a comment, not blank) line from the config file\n */\nchar *CWGetCommand(FILE * configFile)\n{\n\n\tchar *buff = NULL;\n\tchar *command = NULL;\n\tchar *ret = NULL;\n\n\tCW_CREATE_STRING_ERR(buff, CW_BUFFER_SIZE, return NULL;\n\t    );\n\n\t/* skip comments and blank lines */\n\twhile (((ret = CWFgets(buff, CW_BUFFER_SIZE, configFile)) != NULL) &&\n\t       (buff[0] == '\\n' || buff[0] == '\\r' || buff[0] == '#')) ;\n\n\tif (buff != NULL && ret != NULL) {\n\n\t\tint len = strlen(buff);\n\t\tbuff[len - 1] = '\\0';\t/* remove newline */\n\n\t\tCW_CREATE_STRING_ERR(command, len - 1, return NULL;\n\t\t    );\n\t\tstrcpy(command, buff);\n\t}\n\n\tCW_FREE_OBJECT(buff);\n\n\treturn command;\n}\n\n/*\n * Parses the configuration file.\n *\n * Params: isCount  CW_TRUE to just count ACAddresses and paths;\n *          CW_FALSE to actually parse them.\n *\n * Return: CW_TRUE if the operation is succesful; CW_FALSE otherwise.\n */\nCWBool CWParseTheFile(CWBool isCount)\n{\n\n\tchar *line = NULL;\n\tint i;\n\n\tif (!isCount) {\n\n\t\tfor (i = 0; i < gConfigValuesCount; i++) {\n\n\t\t\tif (gConfigValues[i].type == CW_STRING_ARRAY) {\n\n\t\t\t\t/* avoid to allocate 0 bytes */\n\t\t\t\tif (gConfigValues[i].count) {\n\n\t\t\t\t\tCW_CREATE_ARRAY_ERR((gConfigValues[i].value.str_array_value),\n\t\t\t\t\t\t\t    gConfigValues[i].count, char *,\n\t\t\t\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t    );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\n\t\tfor (i = 0; i < gConfigValuesCount; i++) {\n\n\t\t\tif (gConfigValues[i].type == CW_STRING_ARRAY) {\n\n\t\t\t\tgConfigValues[i].count = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tgCWConfigFile = fopen(CW_CONFIG_FILE, \"rb\");\n\tif (gCWConfigFile == NULL)\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\n\twhile ((line = CWGetCommand(gCWConfigFile)) != NULL) {\n\n\t\tint i, j;\n\n\t\tCWDebugLog(\"*** Parsing (%s) ***\", line);\n\n\t\tfor (i = 0; i < gConfigValuesCount; i++) {\n\n\t\t\tif (!strncmp(line, gConfigValues[i].code, strlen(gConfigValues[i].code))) {\n\n\t\t\t\tchar *myLine = line + strlen(gConfigValues[i].code);\n\n\t\t\t\tswitch (gConfigValues[i].type) {\n\n\t\t\t\tcase CW_INTEGER:\n\t\t\t\t\tgConfigValues[i].value.int_value = atoi(myLine);\n\t\t\t\t\tbreak;\n\t\t\t\tcase CW_STRING:\n\t\t\t\t\t/*\n\t\t\t\t\t * BUG - LE02\n\t\t\t\t\t * If this function was called just to count ACAddresses and\n\t\t\t\t\t * paths, we MUST NOT allocate a string value; the actual allocation\n\t\t\t\t\t * will be performed when the function is called with the isCount\n\t\t\t\t\t * argument = CW_FALSE.\n\t\t\t\t\t *\n\t\t\t\t\t * 19/10/2009 - Donato Capitella\n\t\t\t\t\t */\n\n\t\t\t\t\tif (!isCount)\n\t\t\t\t\t\tCW_CREATE_STRING_FROM_STRING_ERR(gConfigValues[i].value.str_value,\n\t\t\t\t\t\t\t\t\t\t myLine,\n\t\t\t\t\t\t\t\t\t\t return\n\t\t\t\t\t\t\t\t\t\t CWErrorRaise(CW_ERROR_OUT_OF_MEMORY,\n\t\t\t\t\t\t\t\t\t\t\t      NULL);\n\t\t\t\t\t    );\n\t\t\t\t\tbreak;\n\t\t\t\tcase CW_STRING_ARRAY:\n#ifdef CW_DEBUGGING\n\t\t\t\t\tCWDebugLog(\"*** Parsing String Array... *** \\n\");\n#endif\n\t\t\t\t\tj = 0;\n\t\t\t\t\tCW_FREE_OBJECT(line);\n\t\t\t\t\twhile ((line = CWGetCommand(gCWConfigFile)) != NULL\n\t\t\t\t\t       && strcmp(line, gConfigValues[i].endCode)) {\n#ifdef CW_DEBUGGING\n\t\t\t\t\t\tCWDebugLog(\"*** Parsing String (%s) *** \\n\", line);\n#endif\n\n\t\t\t\t\t\tif (isCount)\n\t\t\t\t\t\t\tgConfigValues[i].count++;\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tCW_CREATE_STRING_FROM_STRING_ERR((gConfigValues[i].value.\n\t\t\t\t\t\t\t\t\t\t\t  str_array_value)[j], line,\n\t\t\t\t\t\t\t\t\t\t\t return\n\t\t\t\t\t\t\t\t\t\t\t CWErrorRaise\n\t\t\t\t\t\t\t\t\t\t\t (CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t\t\t\t    );\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCW_FREE_OBJECT(line);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tCW_FREE_OBJECT(line);\n\t}\n\n\tCWDebugLog(\"*** Config File Parsed ***\");\n\tfclose(gCWConfigFile);\n\n\treturn CW_TRUE;\n}\n\n/* parses the configuration file */\nCWBool CWParseConfigFile()\n{\n\n\tif (!(CWConfigFileInitLib()))\n\t\treturn CW_FALSE;\n\n\t/* just count the objects */\n\tif (!CWParseTheFile(CW_TRUE))\n\t\treturn CW_FALSE;\n\n\t/* actually parse */\n\tif (!CWParseTheFile(CW_FALSE))\n\t\treturn CW_FALSE;\n\n#ifdef CW_DEBUGGING\n\t{\n\t\tint i;\n\t\tfor (i = 0; i < gConfigValuesCount; i++) {\n\n\t\t\tif (gConfigValues[i].type == CW_INTEGER) {\n\n\t\t\t\tCWLog(\"%s%d\", gConfigValues[i].code, gConfigValues[i].value.int_value);\n\t\t\t}\n\t\t}\n\t}\n\tCWDebugLog(\"*** Config File END ***\");\n#endif\n\n\treturn CWConfigFileDestroyLib();\n}\n"
  },
  {
    "path": "CWConfigFile.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWConfigFile_HEADER__\n#define __CAPWAP_CWConfigFile_HEADER__\n\ntypedef char **CWStringArray;\n\ntypedef struct {\n\tenum {\n\t\tCW_INTEGER,\n\t\tCW_STRING,\n\t\tCW_STRING_ARRAY\n\t} type;\n\n\tunion {\n\t\tint int_value;\n\t\tchar *str_value;\n\t\tchar **str_array_value;\n\t} value;\n\n\tchar *code;\n\tchar *endCode;\n\n\tint count;\n} CWConfigValue;\n\nextern CWConfigValue *gConfigValues;\nextern int gConfigValuesCount;\n\nCWBool CWParseConfigFile();\nchar *CWGetCommand(FILE * configFile);\nCWBool CWConfigFileInitLib(void);\nCWBool CWConfigFileDestroyLib(void);\n\n#endif\n"
  },
  {
    "path": "CWErrorHandling.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#ifndef CW_SINGLE_THREAD\nCWThreadSpecific gLastError;\n//CWThreadOnce gInitLastErrorOnce = CW_THREAD_ONCE_INIT;\n#else\nstatic CWErrorHandlingInfo *gLastErrorDataPtr;\n#endif\n\nvoid CWErrorHandlingInitLib()\n{\n\tCWDebugLog(\"Init Errors \");\n\n#ifndef CW_SINGLE_THREAD\n\tif (!CWThreadCreateSpecific(&gLastError, NULL)) {\n\t\tCWLog(\"Critical Error, closing the process...\");\n\t\texit(1);\n\t}\n#else\n\tCW_CREATE_OBJECT_ERR(infoPtr, CWErrorHandlingInfo, return;\n\t    );\n\tinfoPtr->code = CW_ERROR_NONE;\n\tgLastErrorDataPtr = infoPtr;\n#endif\n}\n\nCWBool _CWErrorRaise(CWErrorCode code, const char *msg, const char *fileName, int line)\n{\n\tCWErrorHandlingInfo *infoPtr;\n\n#ifndef CW_SINGLE_THREAD\n\tinfoPtr = CWThreadGetSpecific(&gLastError);\n\tif (infoPtr == NULL) {\n\t\tCW_CREATE_OBJECT_ERR(infoPtr, CWErrorHandlingInfo, exit(1);\n\t\t    );\n\t\tinfoPtr->code = CW_ERROR_NONE;\n\t\tif (!CWThreadSetSpecific(&gLastError, infoPtr)) {\n\t\t\tCWLog(\"Critical Error, closing the process...\");\n\t\t\texit(1);\n\t\t}\n\t}\n#else\n\tinfoPtr = gLastErrorDataPtr;\n#endif\n\n\tif (infoPtr == NULL) {\n\t\tCWLog(\"Critical Error: something strange has happened, closing the process...\");\n\t\texit(1);\n\t}\n\n\tinfoPtr->code = code;\n\tif (msg != NULL)\n\t\tstrcpy(infoPtr->message, msg);\n\telse\n\t\tinfoPtr->message[0] = '\\0';\n\tif (fileName != NULL)\n\t\tstrcpy(infoPtr->fileName, fileName);\n\tinfoPtr->line = line;\n\n\treturn CW_FALSE;\n}\n\nvoid CWErrorPrint(CWErrorHandlingInfo * infoPtr, const char *desc, const char *fileName, int line)\n{\n\tif (infoPtr == NULL)\n\t\treturn;\n\n\tif (infoPtr->message != NULL && infoPtr->message[0] != '\\0') {\n\t\tCWLog(\"Error: %s. %s .\", desc, infoPtr->message);\n\t} else {\n\t\tCWLog(\"Error: %s\", desc);\n\t}\n\tCWLog(\"(occurred at line %d in file %s, catched at line %d in file %s).\",\n\t      infoPtr->line, infoPtr->fileName, line, fileName);\n}\n\nCWErrorCode CWErrorGetLastErrorCode()\n{\n\tCWErrorHandlingInfo *infoPtr;\n\n#ifndef CW_SINGLE_THREAD\n\tinfoPtr = CWThreadGetSpecific(&gLastError);\n#else\n\tinfoPtr = gLastErrorDataPtr;\n#endif\n\n\tif (infoPtr == NULL)\n\t\treturn CW_ERROR_GENERAL;\n\n\treturn infoPtr->code;\n}\n\nCWBool _CWErrorHandleLast(const char *fileName, int line)\n{\n\tCWErrorHandlingInfo *infoPtr;\n\n#ifndef CW_SINGLE_THREAD\n\tinfoPtr = CWThreadGetSpecific(&gLastError);\n#else\n\tinfoPtr = gLastErrorDataPtr;\n#endif\n\n\tif (infoPtr == NULL) {\n\t\tCWLog(\"No Error Pending\");\n\t\texit((3));\n\t\treturn CW_FALSE;\n\t}\n#define __CW_ERROR_PRINT(str)   CWErrorPrint(infoPtr, (str), fileName, line)\n\n\tswitch (infoPtr->code) {\n\tcase CW_ERROR_SUCCESS:\n\tcase CW_ERROR_NONE:\n\t\treturn CW_TRUE;\n\t\tbreak;\n\n\tcase CW_ERROR_OUT_OF_MEMORY:\n\t\t__CW_ERROR_PRINT(\"Out of Memory\");\n#ifndef CW_SINGLE_THREAD\n\t\tCWExitThread();\t// note: we can manage this on per-thread basis: ex. we can\n\t\t// kill some other thread if we are a manager thread.\n#else\n\t\texit(1);\n#endif\n\t\tbreak;\n\n\tcase CW_ERROR_WRONG_ARG:\n\t\t__CW_ERROR_PRINT(\"Wrong Arguments in Function\");\n\t\tbreak;\n\n\tcase CW_ERROR_NEED_RESOURCE:\n\t\t__CW_ERROR_PRINT(\"Missing Resource\");\n\t\tbreak;\n\n\tcase CW_ERROR_GENERAL:\n\t\t__CW_ERROR_PRINT(\"Error Occurred\");\n\t\tbreak;\n\n\tcase CW_ERROR_CREATING:\n\t\t__CW_ERROR_PRINT(\"Error Creating Resource\");\n\t\tbreak;\n\n\tcase CW_ERROR_SENDING:\n\t\t__CW_ERROR_PRINT(\"Error Sending\");\n\t\tbreak;\n\n\tcase CW_ERROR_RECEIVING:\n\t\t__CW_ERROR_PRINT(\"Error Receiving\");\n\t\tbreak;\n\n\tcase CW_ERROR_INVALID_FORMAT:\n\t\t__CW_ERROR_PRINT(\"Invalid Format\");\n\t\tbreak;\n\n\tcase CW_ERROR_INTERRUPTED:\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn CW_FALSE;\n}\n"
  },
  {
    "path": "CWErrorHandling.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWErrorHandling_HEADER__\n#define __CAPWAP_CWErrorHandling_HEADER__\n\ntypedef enum {\n\tCW_ERROR_SUCCESS = 1,\n\tCW_ERROR_OUT_OF_MEMORY,\n\tCW_ERROR_WRONG_ARG,\n\tCW_ERROR_INTERRUPTED,\n\tCW_ERROR_NEED_RESOURCE,\n\tCW_ERROR_COMUNICATING,\n\tCW_ERROR_CREATING,\n\tCW_ERROR_GENERAL,\n\tCW_ERROR_OPERATION_ABORTED,\n\tCW_ERROR_SENDING,\n\tCW_ERROR_RECEIVING,\n\tCW_ERROR_INVALID_FORMAT,\n\tCW_ERROR_TIME_EXPIRED,\n\tCW_ERROR_NONE\n} CWErrorCode;\n\ntypedef struct {\n\tCWErrorCode code;\n\tchar message[256];\n\tint line;\n\tchar fileName[64];\n} CWErrorHandlingInfo;\n\n#define CWErrorRaiseSystemError(error)      {                   \\\n                            char buf[256];          \\\n                            strerror_r(errno, buf, 256);    \\\n                            CWErrorRaise(error, buf);   \\\n                            return CW_FALSE;        \\\n                        }\n\n#define CWErrorRaise(code, msg)         _CWErrorRaise(code, msg, __FILE__, __LINE__)\n#define CWErr(arg)              ((arg) || _CWErrorHandleLast(__FILE__, __LINE__))\n#define CWErrorHandleLast()         _CWErrorHandleLast(__FILE__, __LINE__)\n\nCWBool _CWErrorRaise(CWErrorCode code, const char *msg, const char *fileName, int line);\nvoid CWErrorPrint(CWErrorHandlingInfo * infoPtr, const char *desc, const char *fileName, int line);\nCWErrorCode CWErrorGetLastErrorCode(void);\nCWBool _CWErrorHandleLast(const char *fileName, int line);\n\n#endif\n"
  },
  {
    "path": "CWFreqPayloads.h",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#ifndef __CAPWAP_Freq_Payloads__\n#define __CAPWAP_Freq_Payloads__\n\n#define CW_FREQ_CELL_INFO_PAYLOAD_SIZE 65\n#define CW_FREQ_ACK_SIZE 8\n\n#endif\n"
  },
  {
    "path": "CWList.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n// adds an element at the head of the list\n// CW_TRUE if the operation is successful, CW_FALSE otherwise\nCWBool CWAddElementToList(CWList * list, void *element)\n{\n\tCWListElement *newElem;\n\n\tif (element == NULL || list == NULL)\n\t\treturn CW_FALSE;\n\n\tif ((*list) == NULL) {\t// first element\n\t\tCW_CREATE_OBJECT_ERR((*list), CWListElement, return CW_FALSE;\n\t\t    );\n\t\t(*list)->data = element;\n\t\t(*list)->next = NULL;\n\t\treturn CW_TRUE;\n\t}\n\n\tCW_CREATE_OBJECT_ERR(newElem, CWListElement, return CW_FALSE;\n\t    );\n\tnewElem->data = element;\n\tnewElem->next = (*list);\n\n\t(*list) = newElem;\n\n\treturn CW_TRUE;\n}\n\n// adds an element at the tail of the list\n// CW_TRUE if the operation is successful, CW_FALSE otherwise\nCWBool CWAddElementToListTail(CWList * list, void *element)\n{\n\tCWListElement *newElem;\n\n\tif (element == NULL || list == NULL)\n\t\treturn CW_FALSE;\n\n\tif ((*list) == NULL) {\t// first element\n\t\tCW_CREATE_OBJECT_ERR((*list), CWListElement, return CW_FALSE;\n\t\t    );\n\t\t(*list)->data = element;\n\t\t(*list)->next = NULL;\n\t\treturn CW_TRUE;\n\t}\n\n\tnewElem = *list;\n\twhile (newElem->next != NULL) {\n\t\tnewElem = newElem->next;\n\t}\n\n\tCW_CREATE_OBJECT_ERR(newElem->next, CWListElement, return CW_FALSE;\n\t    );\n\tnewElem->next->data = element;\n\tnewElem->next->next = NULL;\n\n\treturn CW_TRUE;\n}\n\nCWList CWListGetFirstElem(CWList * list)\n{\n\tCWList auxList;\n\n\tif (list == NULL || *list == NULL)\n\t\treturn NULL;\n\n\tauxList = *list;\n\t*list = (*list)->next;\n\tauxList->next = NULL;\n\n\treturn auxList;\n}\n\n// not thread safe!\nvoid *CWListGetNext(CWList list, CWListIterateMode mode)\n{\n\tstatic CWList l = NULL;\n\tvoid *data;\n\n\tif (list == NULL)\n\t\treturn NULL;\n\n\tif (mode == CW_LIST_ITERATE_RESET) {\n\t\tl = list;\n\t} else if (l == NULL)\n\t\treturn NULL;\n\n\tdata = l->data;\n\tl = l->next;\n\n\treturn data;\n}\n\n// search baseElement in list using compareFunc\n// NULL if there was an error, the element otherwise\nvoid *CWSearchInList(CWList list, void *baseElement, CWBool(*compareFunc) (void *, void *))\n{\n\tCWListElement *el = NULL;\n\n\tif (baseElement == NULL || compareFunc == NULL)\n\t\treturn NULL;\n\n\tfor (el = list; el != NULL; el = el->next) {\n\t\tif (compareFunc(baseElement, el->data)) {\n\t\t\treturn el->data;\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\n// search baseElement in list using compareFunc, removes the element from the list and returns it\n// NULL if there was an error, the element otherwise\nvoid *CWDeleteInList(CWList * list, void *baseElement, CWBool(*compareFunc) (void *, void *))\n{\n\tCWListElement *el = NULL, *oldEl = NULL;\n\n\tif (baseElement == NULL || compareFunc == NULL || list == NULL)\n\t\treturn NULL;\n\n\tfor (el = (*list); el != NULL; oldEl = el, el = el->next) {\n\t\tif (compareFunc(baseElement, el->data)) {\n\t\t\tvoid *data = el->data;\n\t\t\tif (oldEl != NULL) {\n\t\t\t\toldEl->next = el->next;\n\n\t\t\t\tCW_FREE_OBJECT(el);\n\t\t\t\treturn data;\n\t\t\t} else {\t// first element\n\t\t\t\t(*list) = el->next;\n\n\t\t\t\tCW_FREE_OBJECT(el);\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\n// deletes a list, deleting each element with a call to the given deleteFunc\nvoid CWDeleteList(CWList * list, void (*deleteFunc) (void *))\n{\n\tCWListElement *el = NULL;\n\n\tif (list == NULL || (*list) == NULL || deleteFunc == NULL)\n\t\treturn;\n\n\tdo {\n\t\tel = (*list);\n\t\t(*list) = (*list)->next;\n\t\tdeleteFunc(el->data);\n\t\tCW_FREE_OBJECT(el);\n\t} while ((*list) != NULL);\n}\n\nint CWCountElementInList(CWList list)\n{\n\tCWListElement *current;\n\tint count = 0;\n\n\tcurrent = list;\n\twhile (current != NULL) {\n\t\tcount++;\n\t\tcurrent = current->next;\n\t}\n\treturn count;\n}\n\n/*\nCWList *FindLastElementInList (CWList list)\n{\n    CWListElement *current;\n\n    current=list;\n    while (current!= NULL) {current= current->next;}\n    return &current;\n}\n*/\n"
  },
  {
    "path": "CWList.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWList_HEADER__\n#define __CAPWAP_CWList_HEADER__\n\n#define CW_LIST_INIT        NULL\n\ntypedef struct _s {\n\tvoid *data;\n\tstruct _s *next;\n} CWListElement;\n\ntypedef enum {\n\tCW_LIST_ITERATE_RESET,\n\tCW_LIST_ITERATE\n} CWListIterateMode;\n\ntypedef CWListElement *CWList;\n\nCWBool CWAddElementToList(CWList * list, void *element);\nCWBool CWAddElementToListTail(CWList * list, void *element);\nCWList CWListGetFirstElem(CWList * list);\nvoid *CWListGetNext(CWList list, CWListIterateMode mode);\nvoid *CWSearchInList(CWList list, void *baseElement, CWBool(*compareFunc) (void *, void *));\nvoid *CWDeleteInList(CWList * list, void *baseElement, CWBool(*compareFunc) (void *, void *));\nvoid CWDeleteList(CWList * list, void (*deleteFunc) (void *));\nint CWCountElementInList(CWList list);\n//CWList * FindLastElementInList (CWList list);\n\n#endif\n"
  },
  {
    "path": "CWLog.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n//#define WRITE_STD_OUTPUT 1\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nstatic FILE *gLogFile = NULL;\n\n#ifndef CW_SINGLE_THREAD\nCWThreadMutex gFileMutex;\n#endif\n\nvoid CWLogInitFile(char *fileName)\n{\n\tif (fileName == NULL) {\n\t\tCWLog(\"Wrong File Name for Log File\");\n\t}\n\tif ((gLogFile = fopen(fileName, \"w\")) == NULL) {\n\t\tCWLog(\"Can't open log file: %s\", strerror(errno));\n\t\texit(1);\n\t}\n#ifndef CW_SINGLE_THREAD\n\tif (!CWCreateThreadMutex(&gFileMutex)) {\n\t\tCWLog(\"Can't Init File Mutex for Log\");\n\t\texit(1);\n\t}\n#endif\n}\n\nstatic CWBool checkResetFile()\n{\n\tlong fileSize = 0;\n\n\tif ((fileSize = ftell(gLogFile)) == -1) {\n\t\tCWLog(\"An error with log file occurred: %s\", strerror(errno));\n\t\treturn 0;\n\t}\n\tif (fileSize >= gMaxLogFileSize) {\n\t\tfclose(gLogFile);\n\t\tif ((gLogFile = fopen(gLogFileName, \"w\")) == NULL) {\n\t\t\tCWLog(\"Can't open log file: %s\", strerror(errno));\n\t\t\treturn 0;\n\t\t}\n\t}\n\treturn 1;\n}\n\nvoid CWLogCloseFile()\n{\n#ifndef CW_SINGLE_THREAD\n\tCWDestroyThreadMutex(&gFileMutex);\n#endif\n\n\tfclose(gLogFile);\n}\n\nvoid CWVLog(const char *format, va_list args)\n{\n\tchar *logStr = NULL;\n\ttime_t now;\n\tchar *nowReadable = NULL;\n\n\tif (format == NULL)\n\t\treturn;\n\n\tnow = time(NULL);\n\tnowReadable = ctime(&now);\n\n\tnowReadable[strlen(nowReadable) - 1] = '\\0';\n\n\t// return in case of memory err: we're not performing a critical task\n\tCW_CREATE_STRING_ERR(logStr, (strlen(format) + strlen(nowReadable) + 100), return;\n\t    );\n\n\t//sprintf(logStr, \"[CAPWAP::%s]\\t\\t %s\\n\", nowReadable, format);\n\tsprintf(logStr, \"[CAPWAP::%s]\\t%08x\\t %s\\n\", nowReadable, (unsigned int)CWThreadSelf(), format);\n\n\tif (gLogFile != NULL) {\n\t\tchar fileLine[256];\n\n#ifndef CW_SINGLE_THREAD\n\t\tCWThreadMutexLock(&gFileMutex);\n\t\tfseek(gLogFile, 0L, SEEK_END);\n#endif\n\n\t\tvsnprintf(fileLine, 255, logStr, args);\n\n\t\tif (!checkResetFile()) {\n\t\t\tCWThreadMutexUnlock(&gFileMutex);\n\t\t\texit(1);\n\t\t}\n\n\t\tfwrite(fileLine, strlen(fileLine), 1, gLogFile);\n\t\tfflush(gLogFile);\n\n#ifndef CW_SINGLE_THREAD\n\t\tCWThreadMutexUnlock(&gFileMutex);\n#endif\n\t}\n#ifdef WRITE_STD_OUTPUT\n\t//vprintf(logStr, args);\n#endif\n\n\tCW_FREE_OBJECT(logStr);\n}\n\nvoid CWLog(const char *format, ...)\n{\n\tva_list args;\n\n\tva_start(args, format);\n\tif (gEnabledLog) {\n\t\tCWVLog(format, args);\n\t}\n\tva_end(args);\n}\n\nvoid CWDebugLog(const char *format, ...)\n{\n#ifdef CW_DEBUGGING\n\tchar *logStr = NULL;\n\tva_list args;\n\ttime_t now;\n\tchar *nowReadable = NULL;\n\n\tif (!gEnabledLog) {\n\t\treturn;\n\t}\n\n\tif (format == NULL) {\n#ifdef WRITE_STD_OUTPUT\n\t\tprintf(\"\\n\");\n#endif\n\t\treturn;\n\t}\n\n\tnow = time(NULL);\n\tnowReadable = ctime(&now);\n\n\tnowReadable[strlen(nowReadable) - 1] = '\\0';\n\n\t// return in case of memory err: we're not performing a critical task\n\tCW_CREATE_STRING_ERR(logStr, (strlen(format) + strlen(nowReadable) + 100), return;\n\t    );\n\n\t//sprintf(logStr, \"[[CAPWAP::%s]]\\t\\t %s\\n\", nowReadable, format);\n\tsprintf(logStr, \"[CAPWAP::%s]\\t%08x\\t %s\\n\", nowReadable, (unsigned int)CWThreadSelf(), format);\n\n\tva_start(args, format);\n\n\tif (gLogFile != NULL) {\n\t\tchar fileLine[256];\n\n#ifndef CW_SINGLE_THREAD\n\t\tCWThreadMutexLock(&gFileMutex);\n\t\tfseek(gLogFile, 0L, SEEK_END);\n#endif\n\n\t\tvsnprintf(fileLine, 255, logStr, args);\n\n\t\tif (!checkResetFile()) {\n\t\t\tCWThreadMutexUnlock(&gFileMutex);\n\t\t\texit(1);\n\t\t}\n\n\t\tfwrite(fileLine, strlen(fileLine), 1, gLogFile);\n\n\t\tfflush(gLogFile);\n\n#ifndef CW_SINGLE_THREAD\n\t\tCWThreadMutexUnlock(&gFileMutex);\n#endif\n\t}\n#ifdef WRITE_STD_OUTPUT\n\tvprintf(logStr, args);\n#endif\n\n\tva_end(args);\n\tCW_FREE_OBJECT(logStr);\n#endif\n}\n"
  },
  {
    "path": "CWLog.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWLog_HEADER__\n#define __CAPWAP_CWLog_HEADER__\n\nextern char gLogFileName[];\n\nvoid CWVLog(const char *format, va_list args);\nvoid CWLog(const char *format, ...);\nvoid CWDebugLog(const char *format, ...);\nvoid CWLogInitFile(char *fileName);\nvoid CWLogCloseFile();\n#endif\n"
  },
  {
    "path": "CWNetwork.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWNetworkLev3Service gNetworkPreferredFamily = CW_IPv4;\n\n/*\n * Assume address is valid\n */\n__inline__ int CWNetworkGetAddressSize(CWNetworkLev4Address * addrPtr)\n{\n\n\tswitch (((struct sockaddr *)(addrPtr))->sa_family) {\n\n#ifdef  IPV6\n\t\t/* IPv6 is defined in Stevens' library */\n\tcase AF_INET6:\n\t\treturn sizeof(struct sockaddr_in6);\n\t\tbreak;\n#endif\n\tcase AF_INET:\n\tdefault:\n\t\treturn sizeof(struct sockaddr_in);\n\t}\n}\n\n/*\n * Send buf on an unconnected UDP socket. Unsafe means that we don't use DTLS.\n */\nCWBool CWNetworkSendUnsafeUnconnected(CWSocket sock, CWNetworkLev4Address * addrPtr, unsigned char *buf, int len)\n{\n\n\tif (buf == NULL || addrPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWUseSockNtop(addrPtr, CWDebugLog(str);\n\t    );\n\n\twhile (sendto(sock, buf, len, 0, (struct sockaddr *)addrPtr, CWNetworkGetAddressSize(addrPtr)) < 0) {\n\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWNetworkRaiseSystemError(CW_ERROR_SENDING);\n\t}\n\treturn CW_TRUE;\n}\n\n/*\n * Send buf on a \"connected\" UDP socket. Unsafe means that we don't use DTLS.\n */\nCWBool CWNetworkSendUnsafeConnected(CWSocket sock, unsigned char *buf, int len)\n{\n\n\tif (buf == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\twhile (send(sock, buf, len, 0) < 0) {\n\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWNetworkRaiseSystemError(CW_ERROR_SENDING);\n\t}\n\treturn CW_TRUE;\n}\n\n/*\n * Receive a datagram on an connected UDP socket (blocking).\n * Unsafe means that we don't use DTLS.\n */\nCWBool CWNetworkReceiveUnsafeConnected(CWSocket sock, unsigned char *buf, int len, int *readBytesPtr)\n{\n\n\tif (buf == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\twhile ((*readBytesPtr = recv(sock, buf, len, 0)) < 0) {\n\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWNetworkRaiseSystemError(CW_ERROR_RECEIVING);\n\t}\n\treturn CW_TRUE;\n}\n\n/*\n * Receive a datagram on an unconnected UDP socket (blocking).\n * Unsafe means that we don't use DTLS.\n */\nCWBool CWNetworkReceiveUnsafe(CWSocket sock,\n\t\t\t      unsigned char *buf, int len, int flags, CWNetworkLev4Address * addrPtr, int *readBytesPtr)\n{\n\n\tsocklen_t addrLen = sizeof(CWNetworkLev4Address);\n\n\tif (buf == NULL || addrPtr == NULL || readBytesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\twhile ((*readBytesPtr = recvfrom(sock, buf, len, flags, (struct sockaddr *)addrPtr, &addrLen)) < 0) {\n\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWNetworkRaiseSystemError(CW_ERROR_RECEIVING);\n\t}\n\treturn CW_TRUE;\n}\n\n/*\n * Init network for client.\n */\nCWBool CWNetworkInitSocketClient(CWSocket * sockPtr, CWNetworkLev4Address * addrPtr)\n{\n\tint yes = 1;\n#ifdef IPv6\n\tstruct sockaddr_in6 sockaddr;\n#else\n\tstruct sockaddr_in sockaddr;\n#endif\n\tsocklen_t addrlen = sizeof(sockaddr);\n\n\tif (sockPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n#ifdef IPv6\n\tif (((*sockPtr) =\n\t     socket((gNetworkPreferredFamily == CW_IPv4) ? AF_INET : AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {\n#else\n\tif (((*sockPtr) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {\n#endif\n\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tmemset(&sockaddr, 0, addrlen);\n#ifdef IPv6\n\tsockaddr.sin6_family = (gNetworkPreferredFamily == CW_IPv4) ? AF_INET : AF_INET6;\n#else\n\tsockaddr.sin_family = AF_INET;\n#endif\n\tif (bind(*sockPtr, (const struct sockaddr *)&sockaddr, addrlen) < 0) {\n\t\tclose(*sockPtr);\n\t\tCWDebugLog(\"failed to bind Client socket in <%s> line:%d.\\n\", __func__, __LINE__);\n\t\treturn CW_FALSE;\n\t}\n\n\tif (getsockname(*sockPtr, (struct sockaddr *)&sockaddr, &addrlen) < 0)\n\t\tCWNetworkRaiseSystemError(CW_ERROR_GENERAL);\n\n#ifdef IPv6\n\tCWLog(\"Created Client socket on %s UDP port %d\\n\", sockaddr.sin6_family == AF_INET6 ? \"IPv6\" : \"IPv4\", sockaddr.sin6_port);\n#else\n\tCWLog(\"Created Client socket on IPv4 UDP port %d\\n\", sockaddr.sin_port);\n#endif\n\n\t/* NULL addrPtr means that we don't want to connect to a\n\t * specific address */\n\tif (addrPtr != NULL) {\n\t\tCWUseSockNtop(((struct sockaddr *)addrPtr), CWDebugLog(str);\n\t\t    );\n\n\t\tif (connect((*sockPtr), ((struct sockaddr *)addrPtr), CWNetworkGetAddressSize(addrPtr)) < 0) {\n\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t}\n\t}\n\t/* allow sending broadcast packets */\n\tsetsockopt(*sockPtr, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));\n\n\treturn CW_TRUE;\n}\n\n/*\n * Init data channel network for client\n */\nCWBool CWNetworkInitSocketClientDataChannel(CWSocket * sockPtr, CWNetworkLev4Address * addrPtr)\n{\n\n#ifdef IPv6\n\tstruct sockaddr_in6 sockaddr;\n#else\n\tstruct sockaddr_in sockaddr;\n#endif\n\tsocklen_t addrlen = sizeof(sockaddr);\n\tCWNetworkLev4Address addrPtrDataChannel;\n\n\tif (sockPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n#ifdef IPv6\n\tif (((*sockPtr) =\n\t     socket((gNetworkPreferredFamily == CW_IPv4) ? AF_INET : AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {\n#else\n\tif (((*sockPtr) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {\n#endif\n\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tmemset(&sockaddr, 0, addrlen);\n#ifdef IPv6\n\tsockaddr.sin6_family = (gNetworkPreferredFamily == CW_IPv4) ? AF_INET : AF_INET6;\n#else\n\tsockaddr.sin_family = AF_INET;\n\t//sockaddr.sin_port = htons(CW_DATA_PORT);\n#endif\n\tif (bind(*sockPtr, (const struct sockaddr *)&sockaddr, addrlen) < 0) {\n\t\tclose(*sockPtr);\n\t\tCWDebugLog(\"failed to bind Client socket in <%s> line:%d.\\n\", __func__, __LINE__);\n\t\treturn CW_FALSE;\n\t}\n\n\tif (getsockname(*sockPtr, (struct sockaddr *)&sockaddr, &addrlen) < 0)\n\t\tCWNetworkRaiseSystemError(CW_ERROR_GENERAL);\n\n#ifdef IPv6\n\tCWLog(\"Created Client socket on %s UDP data port %d\\n\", sockaddr.sin6_family == AF_INET6 ? \"IPv6\" : \"IPv4\", sockaddr.sin6_port);\n#else\n\tCWLog(\"Created Client socket on IPv4 UDP data port %d\\n\", sockaddr.sin_port);\n#endif\n\n\t/* NULL addrPtr means that we don't want to connect to a\n\t * specific address */\n\tif (addrPtr != NULL) {\n\t\tCW_COPY_NET_ADDR_PTR(&addrPtrDataChannel, addrPtr);\n\t\tsock_set_port_cw((struct sockaddr *)&addrPtrDataChannel, htons(CW_DATA_PORT));\n\t\tCWUseSockNtop((struct sockaddr *)&addrPtrDataChannel, CWDebugLog(str);\n\t\t    );\n\n\t\tif (connect\n\t\t    ((*sockPtr), (struct sockaddr *)&addrPtrDataChannel,\n\t\t     CWNetworkGetAddressSize(&addrPtrDataChannel)) < 0) {\n\n\t\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n\n/*\n* Wrapper for select\n */\nCWBool CWNetworkTimedPollRead(CWSocket sock, struct timeval * timeout)\n{\n\tint r;\n\n\tfd_set fset;\n\n\tif (timeout == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tFD_ZERO(&fset);\n\tFD_SET(sock, &fset);\n\n\tif ((r = select(sock + 1, &fset, NULL, NULL, timeout)) == 0) {\n\n\t\tCWDebugLog(\"Select Time Expired\");\n\t\treturn CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);\n\t} else if (r < 0) {\n\n\t\tCWDebugLog(\"Select Error\");\n\n\t\tif (errno == EINTR) {\n\n\t\t\tCWDebugLog(\"Select Interrupted by signal\");\n\t\t\treturn CWErrorRaise(CW_ERROR_INTERRUPTED, NULL);\n\t\t}\n\n\t\tCWNetworkRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\treturn CW_TRUE;\n}\n\n/*\n * Given an host int the form of C string (e.g. \"192.168.1.2\" or \"localhost\"),\n * returns the address.\n */\nCWBool CWNetworkGetAddressForHost(char *host, CWNetworkLev4Address * addrPtr)\n{\n\n\tstruct addrinfo hints, *res, *ressave;\n\tchar serviceName[5];\n\tCWSocket sock;\n\n\tif (host == NULL || addrPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_ZERO_MEMORY(&hints, sizeof(struct addrinfo));\n\n#ifdef IPv6\n\tif (gNetworkPreferredFamily == CW_IPv6) {\n\t\thints.ai_family = AF_INET6;\n\t\thints.ai_flags = AI_V4MAPPED;\n\t} else {\n\t\thints.ai_family = AF_INET;\n\t}\n#else\n\thints.ai_family = AF_INET;\n#endif\n\thints.ai_socktype = SOCK_DGRAM;\n\n\t/* endianness will be handled by getaddrinfo */\n\tsnprintf(serviceName, 5, \"%d\", CW_CONTROL_PORT);\n\n\tif (getaddrinfo(host, serviceName, &hints, &res) != 0) {\n\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, \"Can't resolve hostname\");\n\t}\n\n\tressave = res;\n\n\tdo {\n\t\tif ((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {\n\t\t\t/* try next address */\n\t\t\tcontinue;\n\t\t}\n\t\t/* success */\n\t\tbreak;\n\t} while ((res = res->ai_next) != NULL);\n\n\tclose(sock);\n\n\tif (res == NULL) {\n\t\t/* error on last iteration */\n\t\tCWNetworkRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tCW_COPY_NET_ADDR_PTR(addrPtr, (res->ai_addr));\n\tfreeaddrinfo(ressave);\n\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "CWNetwork.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWNetwork_HEADER__\n#define __CAPWAP_CWNetwork_HEADER__\n\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netinet/udp.h>\n#include <netdb.h>\n\n#include \"CWStevens.h\"\n\ntypedef int CWSocket;\n\ntypedef struct sockaddr_storage CWNetworkLev4Address;\n\ntypedef enum {\n\tCW_IPv6,\n\tCW_IPv4\n} CWNetworkLev3Service;\n\nextern CWNetworkLev3Service gNetworkPreferredFamily;\n\n#define CW_COPY_NET_ADDR_PTR(addr1, addr2)      sock_cpy_addr_port(((struct sockaddr*)(addr1)), ((struct sockaddr*)(addr2)))\n#define CW_COPY_NET_ADDR(addr1, addr2)      CW_COPY_NET_ADDR_PTR(&(addr1), &(addr2))\n\n#define CWUseSockNtop(sa, block)        {                       \\\n                            char __str[128];            \\\n                            char *str; str = sock_ntop_r(((struct sockaddr*)(sa)), __str);\\\n                            {block}                 \\\n                        }\n\n#define CWNetworkRaiseSystemError(error)    {                       \\\n                            char buf[256];              \\\n                            if(strerror_r(errno, buf, 256) < 0) {   \\\n                                CWErrorRaise(error, NULL);  \\\n                                return CW_FALSE;        \\\n                            }                   \\\n                            CWErrorRaise(error, NULL);      \\\n                            return CW_FALSE;            \\\n                        }\n\n#define     CWNetworkCloseSocket(x)     { shutdown(SHUT_RDWR, x); close(x); }\n\nint CWNetworkGetAddressSize(CWNetworkLev4Address * addrPtr);\nCWBool CWNetworkSendUnsafeConnected(CWSocket sock, unsigned char *buf, int len);\nCWBool CWNetworkSendUnsafeUnconnected(CWSocket sock, CWNetworkLev4Address * addrPtr, unsigned char *buf, int len);\nCWBool CWNetworkReceiveUnsafe(CWSocket sock, unsigned char *buf, int len, int flags, CWNetworkLev4Address * addrPtr,\n\t\t\t      int *readBytesPtr);\nCWBool CWNetworkReceiveUnsafeConnected(CWSocket sock, unsigned char *buf, int len, int *readBytesPtr);\nCWBool CWNetworkInitSocketClient(CWSocket * sockPtr, CWNetworkLev4Address * addrPtr);\nCWBool CWNetworkInitSocketClientDataChannel(CWSocket * sockPtr, CWNetworkLev4Address * addrPtr);\nCWBool CWNetworkTimedPollRead(CWSocket sock, struct timeval *timeout);\nCWBool CWNetworkGetAddressForHost(char *host, CWNetworkLev4Address * addrPtr);\n\n//CWBool CWNetworkInitLib(void);\n//CWBool CWNetworkInitSocketServer(CWSocket *sockPtr, int port);\n//CWBool CWNetworkSendUnsafeConnected(CWSocket sock, const char *buf, int len);\n\n#endif\n"
  },
  {
    "path": "CWOpenSSLBio.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nstatic int memory_write(BIO * h, const char *buf, int num);\nstatic int memory_read(BIO * h, char *buf, int size);\nstatic int memory_puts(BIO * h, const char *str);\nstatic long memory_ctrl(BIO * h, int cmd, long arg1, void *arg2);\nstatic int memory_new(BIO * h);\nstatic int memory_free(BIO * data);\n\n#ifndef IP_MTU\n#define IP_MTU      14\n#endif\n\ntypedef struct {\n\tCWSocket sock;\n\tCWNetworkLev4Address sendAddress;\n\tCWSafeList *pRecvAddress;\n\tunsigned int nMtu;\n} BIO_memory_data;\n\nstatic BIO_METHOD methods_memory = {\n\tBIO_TYPE_DGRAM,\n\t\"memory packet\",\n\tmemory_write,\n\tmemory_read,\n\tmemory_puts,\n\tNULL,\t\t\t/* dgram_gets, */\n\tmemory_ctrl,\n\tmemory_new,\n\tmemory_free,\n\tNULL,\n};\n\nBIO_METHOD *BIO_s_memory(void)\n{\n\treturn (&methods_memory);\n}\n\nBIO *BIO_new_memory(CWSocket sock, CWNetworkLev4Address * pSendAddress, CWSafeList * pRecvAddress)\n{\n\tBIO *ret;\n\tBIO_memory_data *pData;\n\n\tret = BIO_new(BIO_s_memory());\n\tif (ret == NULL)\n\t\treturn NULL;\n\n\t//\n\tpData = (BIO_memory_data *) ret->ptr;\n\tpData->sock = sock;\n\tmemcpy(&pData->sendAddress, pSendAddress, sizeof(CWNetworkLev4Address));\n\tpData->pRecvAddress = pRecvAddress;\n\n\treturn ret;\n}\n\nstatic int memory_new(BIO * bi)\n{\n\tbi->init = 1;\n\tbi->num = 0;\n\tbi->flags = 0;\n\tbi->ptr = (char *)malloc(sizeof(BIO_memory_data));\n\n\treturn 1;\n}\n\nstatic int memory_free(BIO * a)\n{\n\tif (a == NULL)\n\t\treturn 0;\n\n\tfree(a->ptr);\n\treturn 1;\n}\n\nstatic int memory_read(BIO * b, char *out, int outl)\n{\n\tint ret = -1;\n\tchar *buf;\n\tint size;\n\tBIO_memory_data *pData = (BIO_memory_data *) b->ptr;\n\n\t//\n\t//BIO_clear_retry_flags(b);\n\n\t//\n\tCWLockSafeList(pData->pRecvAddress);\n\n\t// Used only in DTLS handshake\n\twhile (CWGetCountElementFromSafeList(pData->pRecvAddress) == 0) {\n\t\tCWWaitElementFromSafeList(pData->pRecvAddress);\n\t}\n\n\tbuf = (char *)CWRemoveHeadElementFromSafeList(pData->pRecvAddress, &size);\n\n\tCWUnlockSafeList(pData->pRecvAddress);\n\n\tif ((buf == NULL) || (size <= 0))\n\t\tCWLog(\"Warning empty buffer\");\n\telse {\n\t\tret = ((size < outl) ? size : outl) - 4;\n\t\tmemcpy(out, buf + 4, ret);\n\t\tCW_FREE_OBJECT(buf);\n\t}\n\n\treturn ret;\n}\n\nstatic int memory_write(BIO * b, const char *in, int inl)\n{\n\tint ret = -1;\n\tchar strBuffer[MAX_UDP_PACKET_SIZE];\n\tBIO_memory_data *pData = (BIO_memory_data *) b->ptr;\n\n\t//\n\tstrBuffer[0] = (char)(CW_PROTOCOL_VERSION << 4) | (char)(CW_PACKET_CRYPT);\n\tstrBuffer[1] = strBuffer[2] = strBuffer[3] = 0;\n\n\t//\n\tmemcpy(&strBuffer[4], in, inl);\n\n\t//\n\terrno = 0;\n\tret =\n\t    sendto(pData->sock, strBuffer, inl + 4, 0, (struct sockaddr *)&pData->sendAddress,\n\t\t   sizeof(struct sockaddr_storage));\n\n\t//BIO_clear_retry_flags(b);\n\tif (ret <= 0) {\n\t\tif (errno == EINTR)\n\t\t\tBIO_set_retry_write(b);\n\t} else {\n\t\tret -= 4;\n\t}\n\n\treturn ret;\n}\n\nstatic long memory_ctrl(BIO * b, int cmd, long num, void *ptr)\n{\n\tlong ret = 1;\n\tlong sockopt_val = 0;\n\tunsigned int sockopt_len = 0;\n\tBIO_memory_data *pData = (BIO_memory_data *) b->ptr;\n\n\tswitch (cmd) {\n\tcase BIO_CTRL_RESET:\n\t\tret = 0;\n\t\tbreak;\n\n\tcase BIO_CTRL_EOF:\n\t\tret = 0;\n\t\tbreak;\n\n\tcase BIO_CTRL_INFO:\n\t\tret = 0;\n\t\tbreak;\n\n\tcase BIO_CTRL_GET_CLOSE:\n\t\tret = 0;\n\t\tbreak;\n\n\tcase BIO_CTRL_SET_CLOSE:\n\t\tbreak;\n\n\tcase BIO_CTRL_WPENDING:\n\t\tret = 0;\n\t\tbreak;\n\n\tcase BIO_CTRL_PENDING:\n\t\tret = 0;\n\t\tbreak;\n\n\tcase BIO_CTRL_DUP:\n\t\tret = 1;\n\t\tbreak;\n\n\tcase BIO_CTRL_FLUSH:\n\t\tret = 1;\n\t\tbreak;\n\n\tcase BIO_CTRL_PUSH:\n\t\tret = 0;\n\t\tbreak;\n\n\tcase BIO_CTRL_POP:\n\t\tret = 0;\n\n\tcase BIO_CTRL_DGRAM_QUERY_MTU:{\n\t\t\tsockopt_len = sizeof(sockopt_val);\n\t\t\tif ((ret = getsockopt(pData->sock, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, &sockopt_len)) < 0\n\t\t\t    || sockopt_val < 0) {\n\t\t\t\tret = 0;\n\t\t\t} else {\n\t\t\t\tpData->nMtu = sockopt_val;\n\t\t\t\tret = sockopt_val;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\tcase BIO_CTRL_DGRAM_GET_MTU:\n\t\tret = pData->nMtu;\n\t\tbreak;\n\n\tcase BIO_CTRL_DGRAM_SET_MTU:\n\t\tpData->nMtu = num;\n\t\tret = num;\n\t\tbreak;\n\n\tdefault:\n\t\tret = 0;\n\t\tbreak;\n\t}\n\n\treturn ret;\n}\n\nstatic int memory_puts(BIO * bp, const char *str)\n{\n\treturn memory_write(bp, str, strlen(str));\n}\n"
  },
  {
    "path": "CWProtocol.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n#include \"CWVendorPayloads.h\"\n#include \"WUM.h\"\npthread_mutex_t gRADIO_MAC_mutex;\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nstatic const int gCWIANATimes256 = CW_IANA_ENTERPRISE_NUMBER * 256;\nstatic const int gMaxDTLSHeaderSize = 25;\t// see http://crypto.stanford.edu/~nagendra/papers/dtls.pdf\nstatic const int gMaxCAPWAPHeaderSize = 8;\t// note: this include optional Wireless field\nunsigned char gRADIO_MAC[6];\t\t// note: this include optional Wireless field\n\n// stores 8 bits in the message, increments the current offset in bytes\nvoid CWProtocolStore8(CWProtocolMessage * msgPtr, unsigned char val)\n{\n\tCW_COPY_MEMORY(&((msgPtr->msg)[(msgPtr->offset)]), &(val), 1);\n\t(msgPtr->offset) += 1;\n}\n\n// stores 16 bits in the message, increments the current offset in bytes\nvoid CWProtocolStore16(CWProtocolMessage * msgPtr, unsigned short val)\n{\n\tval = htons(val);\n\tCW_COPY_MEMORY(&((msgPtr->msg)[(msgPtr->offset)]), &(val), 2);\n\t(msgPtr->offset) += 2;\n}\n\n// stores 32 bits in the message, increments the current offset in bytes\nvoid CWProtocolStore32(CWProtocolMessage * msgPtr, unsigned int val)\n{\n\tval = htonl(val);\n\tCW_COPY_MEMORY(&((msgPtr->msg)[(msgPtr->offset)]), &(val), 4);\n\t(msgPtr->offset) += 4;\n}\n\n// stores a string in the message, increments the current offset in bytes. Doesn't store\n// the '\\0' final character.\nvoid CWProtocolStoreStr(CWProtocolMessage * msgPtr, char *str)\n{\n\tint len = strlen(str);\n\tCW_COPY_MEMORY(&((msgPtr->msg)[(msgPtr->offset)]), str, len);\n\t(msgPtr->offset) += len;\n}\n\n// stores another message in the message, increments the current offset in bytes.\nvoid CWProtocolStoreMessage(CWProtocolMessage * msgPtr, CWProtocolMessage * msgToStorePtr)\n{\n\tCW_COPY_MEMORY(&((msgPtr->msg)[(msgPtr->offset)]), msgToStorePtr->msg, msgToStorePtr->offset);\n\t(msgPtr->offset) += msgToStorePtr->offset;\n}\n\n// stores len bytes in the message, increments the current offset in bytes.\nvoid CWProtocolStoreRawBytes(CWProtocolMessage * msgPtr, unsigned char *bytes, int len)\n{\n\tCW_COPY_MEMORY(&((msgPtr->msg)[(msgPtr->offset)]), bytes, len);\n\t(msgPtr->offset) += len;\n}\n\n// retrieves 8 bits from the message, increments the current offset in bytes.\nunsigned char CWProtocolRetrieve8(CWProtocolMessage * msgPtr)\n{\n\tunsigned char val;\n\n\tCW_COPY_MEMORY(&val, &((msgPtr->msg)[(msgPtr->offset)]), 1);\n\t(msgPtr->offset) += 1;\n\n\treturn val;\n}\n\n// retrieves 16 bits from the message, increments the current offset in bytes.\nunsigned short CWProtocolRetrieve16(CWProtocolMessage * msgPtr)\n{\n\tunsigned short val;\n\n\tCW_COPY_MEMORY(&val, &((msgPtr->msg)[(msgPtr->offset)]), 2);\n\t(msgPtr->offset) += 2;\n\n\treturn ntohs(val);\n}\n\n// retrieves 32 bits from the message, increments the current offset in bytes.\nunsigned int CWProtocolRetrieve32(CWProtocolMessage * msgPtr)\n{\n\tunsigned int val;\n\n\tCW_COPY_MEMORY(&val, &((msgPtr->msg)[(msgPtr->offset)]), 4);\n\t(msgPtr->offset) += 4;\n\n\treturn ntohl(val);\n}\n\n// retrieves a string (not null-terminated) from the message, increments the current offset in bytes.\n// Adds the '\\0' char at the end of the string which is returned\nchar *CWProtocolRetrieveStr(CWProtocolMessage * msgPtr, int len)\n{\n\tchar *str;\n\n\tCW_CREATE_OBJECT_SIZE_ERR(str, (len + 1), return NULL;\n\t    );\n\n\tCW_COPY_MEMORY(str, &((msgPtr->msg)[(msgPtr->offset)]), len);\n\tstr[len] = '\\0';\n\t(msgPtr->offset) += len;\n\n\treturn str;\n}\n\n// retrieves len bytes from the message, increments the current offset in bytes.\nunsigned char *CWProtocolRetrieveRawBytes(CWProtocolMessage * msgPtr, unsigned int len)\n{\n\tunsigned char *bytes;\n\n\tCW_CREATE_OBJECT_SIZE_ERR(bytes, len, return NULL;\n\t    );\n\n\tCW_COPY_MEMORY(bytes, &((msgPtr->msg)[(msgPtr->offset)]), len);\n\t(msgPtr->offset) += len;\n\n\treturn bytes;\n}\n\nvoid CWProtocolDestroyMsgElemData(void *f)\n{\n\tCW_FREE_OBJECT(f);\n}\n\n// Assemble a Message Element creating the appropriate header and storing the message.\nCWBool CWAssembleMsgElem(CWProtocolMessage * msgPtr, unsigned int type)\n{\n\tCWProtocolMessage completeMsg;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(completeMsg, 6 + (msgPtr->offset), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t// store header\n\tCWProtocolStore16(&completeMsg, type);\n\tCWProtocolStore16(&completeMsg, msgPtr->offset);\t// size of the body\n\n\t// store body\n\tCWProtocolStoreMessage(&completeMsg, msgPtr);\n\n\tCW_FREE_PROTOCOL_MESSAGE(*msgPtr);\n\n\tmsgPtr->msg = completeMsg.msg;\n\tmsgPtr->offset = completeMsg.offset;\n\n\treturn CW_TRUE;\n}\n\n// Assembles the Transport Header\nCWBool CWAssembleTransportHeader(CWProtocolMessage * transportHdrPtr, CWProtocolTransportHeaderValues * valuesPtr)\n{\n\n\tchar radio_mac_present = 0;\n\tint i;\n\n\tfor (i = 0; i < 6; i++) {\n\t\t//printf(\":::: %02X\\n\",gRADIO_MAC[i]);\n\t\tif (gRADIO_MAC[i] != 0) {\n\t\t\tradio_mac_present = 8;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tunsigned int val = 0;\n\tif (transportHdrPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (valuesPtr->bindingValuesPtr != NULL) {\n\t\tCW_CREATE_PROTOCOL_MESSAGE(*transportHdrPtr, gMaxCAPWAPHeaderSizeBinding + radio_mac_present,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t} else {\n\t\tCW_CREATE_PROTOCOL_MESSAGE(*transportHdrPtr, 8 + radio_mac_present,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\t\t// meaningful bytes of the header (no wirless header and MAC address)\n\t}\n\tCWSetField32(val, CW_TRANSPORT_HEADER_VERSION_START, CW_TRANSPORT_HEADER_VERSION_LEN, CW_PROTOCOL_VERSION);\t// current version of CAPWAP\n\n\tCWSetField32(val,\n\t\t     CW_TRANSPORT_HEADER_TYPE_START,\n\t\t     CW_TRANSPORT_HEADER_TYPE_LEN, (valuesPtr->payloadType == CW_PACKET_PLAIN) ? 0 : 1);\n\n\tif (radio_mac_present)\n\t\tif (valuesPtr->bindingValuesPtr != NULL)\n\t\t\tCWSetField32(val,\n\t\t\t\t     CW_TRANSPORT_HEADER_HLEN_START, CW_TRANSPORT_HEADER_HLEN_LEN, (CW_BINDING_HLEN + 2));\n\t\telse\n\t\t\tCWSetField32(val, CW_TRANSPORT_HEADER_HLEN_START, CW_TRANSPORT_HEADER_HLEN_LEN, (2 + 2));\n\telse if (valuesPtr->bindingValuesPtr != NULL)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_HLEN_START, CW_TRANSPORT_HEADER_HLEN_LEN, CW_BINDING_HLEN);\n\telse\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_HLEN_START, CW_TRANSPORT_HEADER_HLEN_LEN, 2);\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_RID_START, CW_TRANSPORT_HEADER_RID_LEN, 0);\t// only one radio per WTP?\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_WBID_START, CW_TRANSPORT_HEADER_WBID_LEN, 1);\t// Wireless Binding ID\n\n\tif (valuesPtr->bindingValuesPtr != NULL)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_T_START, CW_TRANSPORT_HEADER_T_LEN, 1);\n\n\telse if (valuesPtr->type == 1)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_T_START, CW_TRANSPORT_HEADER_T_LEN, 1);\n\telse\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_T_START, CW_TRANSPORT_HEADER_T_LEN, 0);\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_F_START, CW_TRANSPORT_HEADER_F_LEN, valuesPtr->isFragment);\t// is fragment\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_L_START, CW_TRANSPORT_HEADER_L_LEN, valuesPtr->last);\t// last fragment\n\n\tif (valuesPtr->bindingValuesPtr != NULL)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_W_START, CW_TRANSPORT_HEADER_W_LEN, 1);\t//wireless header\n\telse\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_W_START, CW_TRANSPORT_HEADER_W_LEN, 0);\n\n\tif (radio_mac_present)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_M_START, CW_TRANSPORT_HEADER_M_LEN, 1);\t//radio MAC address\n\telse\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_M_START, CW_TRANSPORT_HEADER_M_LEN, 0);\t// no radio MAC address\n\tCWSetField32(val, CW_TRANSPORT_HEADER_K_START, CW_TRANSPORT_HEADER_K_LEN, 0);\t// Keep alive flag\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_FLAGS_START, CW_TRANSPORT_HEADER_FLAGS_LEN, 0);\t// required\n\n\tCWProtocolStore32(transportHdrPtr, val);\n\t// end of first 32 bits\n\n\tval = 0;\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_FRAGMENT_ID_START, CW_TRANSPORT_HEADER_FRAGMENT_ID_LEN, valuesPtr->fragmentID);\t// fragment ID\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_START, CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_LEN, valuesPtr->fragmentOffset);\t// fragment offset\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_RESERVED_START, CW_TRANSPORT_HEADER_RESERVED_LEN, 0);\t// required\n\n\tCWProtocolStore32(transportHdrPtr, val);\n\t// end of second 32 bits\n\n\tif (radio_mac_present) {\n\t\tCWProtocolStore8(transportHdrPtr, 6);\n\n\t\tCWThreadMutexLock(&gRADIO_MAC_mutex);\n\t\tCWProtocolStoreRawBytes(transportHdrPtr, gRADIO_MAC, 6);\n\t\tCWThreadMutexUnlock(&gRADIO_MAC_mutex);\n\n\t\tCWProtocolStore8(transportHdrPtr, 0);\n\t}\n\n\tif (valuesPtr->bindingValuesPtr != NULL) {\n\t\tif (!CWAssembleTransportHeaderBinding(transportHdrPtr, valuesPtr->bindingValuesPtr))\n\t\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\n// Assembles the Transport Header\nCWBool CWAssembleTransportHeaderKeepAliveData(CWProtocolMessage * transportHdrPtr,\n\t\t\t\t\t      CWProtocolTransportHeaderValues * valuesPtr, int keepAlive)\n{\n\n\tunsigned int val = 0;\n\tif (transportHdrPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (valuesPtr->bindingValuesPtr != NULL) {\n\t\tCW_CREATE_PROTOCOL_MESSAGE(*transportHdrPtr, gMaxCAPWAPHeaderSizeBinding,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t} else {\n\t\tCW_CREATE_PROTOCOL_MESSAGE(*transportHdrPtr, 8, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\t\t// meaningful bytes of the header (no wirless header and MAC address)\n\t}\n\tCWSetField32(val, CW_TRANSPORT_HEADER_VERSION_START, CW_TRANSPORT_HEADER_VERSION_LEN, CW_PROTOCOL_VERSION);\t// current version of CAPWAP\n\n\tCWSetField32(val,\n\t\t     CW_TRANSPORT_HEADER_TYPE_START,\n\t\t     CW_TRANSPORT_HEADER_TYPE_LEN, (valuesPtr->payloadType == CW_PACKET_PLAIN) ? 0 : 1);\n\n\tif (valuesPtr->bindingValuesPtr != NULL)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_HLEN_START, CW_TRANSPORT_HEADER_HLEN_LEN, CW_BINDING_HLEN);\n\telse\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_HLEN_START, CW_TRANSPORT_HEADER_HLEN_LEN, 2);\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_RID_START, CW_TRANSPORT_HEADER_RID_LEN, 0);\t// only one radio per WTP?\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_WBID_START, CW_TRANSPORT_HEADER_WBID_LEN, 1);\t// Wireless Binding ID\n\n\tif (valuesPtr->bindingValuesPtr != NULL)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_T_START, CW_TRANSPORT_HEADER_T_LEN, 1);\n\telse\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_T_START, CW_TRANSPORT_HEADER_T_LEN, 0);\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_F_START, CW_TRANSPORT_HEADER_F_LEN, valuesPtr->isFragment);\t// is fragment\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_L_START, CW_TRANSPORT_HEADER_L_LEN, valuesPtr->last);\t// last fragment\n\n\tif (valuesPtr->bindingValuesPtr != NULL)\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_W_START, CW_TRANSPORT_HEADER_W_LEN, 1);\t//wireless header\n\telse\n\t\tCWSetField32(val, CW_TRANSPORT_HEADER_W_START, CW_TRANSPORT_HEADER_W_LEN, 0);\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_M_START, CW_TRANSPORT_HEADER_M_LEN, 0);\t// no radio MAC address\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_K_START, CW_TRANSPORT_HEADER_K_LEN, keepAlive);\t// Keep alive flag\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_FLAGS_START, CW_TRANSPORT_HEADER_FLAGS_LEN, 0);\t// required\n\n\tCWProtocolStore32(transportHdrPtr, val);\n\t// end of first 32 bits\n\n\tval = 0;\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_FRAGMENT_ID_START, CW_TRANSPORT_HEADER_FRAGMENT_ID_LEN, valuesPtr->fragmentID);\t// fragment ID\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_START, CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_LEN, valuesPtr->fragmentOffset);\t// fragment offset\n\n\tCWSetField32(val, CW_TRANSPORT_HEADER_RESERVED_START, CW_TRANSPORT_HEADER_RESERVED_LEN, 0);\t// required\n\n\tCWProtocolStore32(transportHdrPtr, val);\n\t// end of second 32 bits\n\n\tif (valuesPtr->bindingValuesPtr != NULL) {\n\t\tif (!CWAssembleTransportHeaderBinding(transportHdrPtr, valuesPtr->bindingValuesPtr))\n\t\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\n// Assembles the Control Header\nCWBool CWAssembleControlHeader(CWProtocolMessage * controlHdrPtr, CWControlHeaderValues * valPtr)\n{\n\tif (controlHdrPtr == NULL || valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*controlHdrPtr, 8,\t// meaningful bytes of the header\n\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore32(controlHdrPtr, valPtr->messageTypeValue);\n\tCWProtocolStore8(controlHdrPtr, valPtr->seqNum);\n\tCWProtocolStore16(controlHdrPtr, (CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS + (valPtr->msgElemsLen)));\t// 7 is for the next 8+32+16 bits (= 7 bytes), MessageElementsLength+flags + timestamp\n\tCWProtocolStore8(controlHdrPtr, 0);\t// flags\n\t//CWProtocolStore32(controlHdrPtr, ((unsigned int)(time(NULL))) ); // timestamp\n\n\treturn CW_TRUE;\n}\n\n/*Update 2009:\n    Attach a payload with a result code to the message */\nCWBool CWAssembleVendorMsgElemResultCodeWithPayload(CWProtocolMessage * msgPtr, CWProtocolResultCode code,\n\t\t\t\t\t\t    CWProtocolVendorSpecificValues * payload)\n{\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tint payloadSize = 0;\n        CWVendorUciValues *uciPayload;\n\tCWVendorWumValues *wumPayload;\n\tuciPayload = (CWVendorUciValues *) payload->payload;\n\twumPayload = (CWVendorWumValues *) payload->payload;\n\n\tswitch (payload->vendorPayloadType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\twumPayload = NULL;\n\t\tif (uciPayload->response != NULL)\n\t\t\tpayloadSize = (strlen(uciPayload->response) * sizeof(unsigned char));\n\t\tbreak;\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\tuciPayload = NULL;\n\t\tpayloadSize = sizeof(unsigned char);\t/* default, only type */\n\t\tif (wumPayload->type == WTP_VERSION_RESPONSE)\n\t\t\tpayloadSize = sizeof(unsigned char) * 4;\n\t\tbreak;\n\tdefault:\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Invalid vendorPayloadType\");\n\t}\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, (sizeof(unsigned short) * 2) + (sizeof(unsigned int) * 2) + payloadSize,\n\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore32(msgPtr, code);\n//  CWDebugLog(\"Result Code: %d\", code);\n//\n\tswitch (payload->vendorPayloadType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\t/*Store what type of payload we have */\n\t\tCWProtocolStore16(msgPtr, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE);\n\t\t/*Store what type of vendor payload we have */\n\t\tCWProtocolStore16(msgPtr, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI);\n\t\t/*Store payload size */\n\t\tCWProtocolStore32(msgPtr, payloadSize);\n\t\tif (uciPayload->response != NULL)\n\t\t\t/*Store the payload */\n\t\t\tCWProtocolStoreStr(msgPtr, uciPayload->response);\n\t\tbreak;\n\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\t/* Store what type of payload we have */\n\t\tCWProtocolStore16(msgPtr, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE);\n\t\t/* Store what type of vendor payload we have */\n\t\tCWProtocolStore16(msgPtr, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM);\n\t\t/* Store payload size */\n\t\tCWProtocolStore32(msgPtr, payloadSize);\n\n\t\tCWProtocolStore8(msgPtr, wumPayload->type);\n\n\t\tif (wumPayload->type == WTP_VERSION_RESPONSE) {\n\t\t\tCWProtocolStore8(msgPtr, wumPayload->_major_v_);\n\t\t\tCWProtocolStore8(msgPtr, wumPayload->_minor_v_);\n\t\t\tCWProtocolStore8(msgPtr, wumPayload->_revision_v_);\n\t\t}\n\t\tbreak;\n\t}\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE_WITH_PAYLOAD);\n}\n\nCWBool CWAssembleMsgElemResultCode(CWProtocolMessage * msgPtr, CWProtocolResultCode code)\n{\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 4, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore32(msgPtr, code);\n//  CWDebugLog(\"Result Code: %d\", code);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE);\n}\n\n// Assemble a CAPWAP Control Packet, with the given Message Elements, Sequence Number and Message Type. Create Transport and Control Headers.\n// completeMsgPtr is an array of fragments (can be of size 1 if the packet doesn't need fragmentation\nCWBool CWAssembleMessage(CWProtocolMessage ** completeMsgPtr, int *fragmentsNumPtr, int PMTU, int seqNum,\n\t\t\t int msgTypeValue, CWProtocolMessage * msgElems, const int msgElemNum,\n\t\t\t CWProtocolMessage * msgElemsBinding, const int msgElemBindingNum)\n{\n\tCWDebugLog(\"CWAssembleMessage()\");\n\tCWProtocolMessage transportHdr, controlHdr, msg;\n\tint msgElemsLen = 0;\n\tint i;\n\n\tCWProtocolTransportHeaderValues transportVal;\n\tCWControlHeaderValues controlVal;\n\n\tif (completeMsgPtr == NULL || fragmentsNumPtr == NULL || (msgElems == NULL && msgElemNum > 0)\n\t    || (msgElemsBinding == NULL && msgElemBindingNum > 0))\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t//Calculate the whole size of the Msg Elements\n\tfor (i = 0; i < msgElemNum; i++)\n\t\tmsgElemsLen += msgElems[i].offset;\n\tfor (i = 0; i < msgElemBindingNum; i++)\n\t\tmsgElemsLen += msgElemsBinding[i].offset;\n\n\t//Assemble Control Header\n\tcontrolVal.messageTypeValue = msgTypeValue;\n\tcontrolVal.msgElemsLen = msgElemsLen;\n\tcontrolVal.seqNum = seqNum;\n\n\tif (!(CWAssembleControlHeader(&controlHdr, &controlVal))) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(controlHdr);\n\t\tfor (i = 0; i < msgElemNum; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\tfor (i = 0; i < msgElemBindingNum; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElemsBinding[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElemsBinding);\n\t\treturn CW_FALSE;\t// will be handled by the caller\n\t}\n\t// assemble the message putting all the data consecutively\n\tCW_CREATE_PROTOCOL_MESSAGE(msg, controlHdr.offset + msgElemsLen,\n\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStoreMessage(&msg, &controlHdr);\n\tfor (i = 0; i < msgElemNum; i++) {\t// store in the request all the Message Elements\n\t\tCWProtocolStoreMessage(&msg, &(msgElems[i]));\n\t}\n\tfor (i = 0; i < msgElemBindingNum; i++) {\t// store in the request all the Message Elements\n\t\tCWProtocolStoreMessage(&msg, &(msgElemsBinding[i]));\n\t}\n\n\t//Free memory not needed anymore\n\tCW_FREE_PROTOCOL_MESSAGE(controlHdr);\n\tfor (i = 0; i < msgElemNum; i++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t}\n\tCW_FREE_OBJECT(msgElems);\n\tfor (i = 0; i < msgElemBindingNum; i++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgElemsBinding[i]);\n\t}\n\tCW_FREE_OBJECT(msgElemsBinding);\n\n\tCWDebugLog(\"PMTU: %d\", PMTU);\n\n\t// handle fragmentation\n\tPMTU = PMTU - gMaxDTLSHeaderSize - gMaxCAPWAPHeaderSize;\n\n\tif (PMTU > 0) {\n\t\tPMTU = (PMTU / 8) * 8;\t// CAPWAP fragments are made of groups of 8 bytes\n\t\tif (PMTU == 0)\n\t\t\tgoto cw_dont_fragment;\n\n\t\tCWDebugLog(\"Aligned PMTU: %d\", PMTU);\n\t\t*fragmentsNumPtr = msg.offset / PMTU;\n\t\tif ((msg.offset % PMTU) != 0)\n\t\t\t(*fragmentsNumPtr)++;\n\t\tCWDebugLog(\"Fragments #: %d\", *fragmentsNumPtr);\n\t} else {\n cw_dont_fragment:\n\t\t*fragmentsNumPtr = 1;\n\t}\n\n\ttransportVal.bindingValuesPtr = NULL;\n\n\tif (*fragmentsNumPtr == 1) {\n\t\tCWDebugLog(\"1 Fragment\");\n\n\t\tCW_CREATE_OBJECT_ERR(*completeMsgPtr, CWProtocolMessage,\n\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\ttransportVal.isFragment = transportVal.last = transportVal.fragmentOffset = transportVal.fragmentID = 0;\n\t\ttransportVal.payloadType = CW_PACKET_PLAIN;\n//      transportVal.last = 1;\n\n\t\t// Assemble Message Elements\n\t\tif (!(CWAssembleTransportHeader(&transportHdr, &transportVal))) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t}\n\t\t// assemble the message putting all the data consecutively\n\t\tCW_CREATE_PROTOCOL_MESSAGE(((*completeMsgPtr)[0]), transportHdr.offset + msg.offset,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tCWProtocolStoreMessage(&((*completeMsgPtr)[0]), &transportHdr);\n\t\tCWProtocolStoreMessage(&((*completeMsgPtr)[0]), &msg);\n\n\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t} else {\n\t\tint fragID = CWGetFragmentID();\n\t\tint totalSize = msg.offset;\n\t\tCWDebugLog(\"%d Fragments\", *fragmentsNumPtr);\n\n\t\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(*completeMsgPtr, *fragmentsNumPtr,\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tmsg.offset = 0;\n\n\t\tfor (i = 0; i < *fragmentsNumPtr; i++) {\t// for each fragment to assemble\n\t\t\tint fragSize;\n\n\t\t\ttransportVal.isFragment = 1;\n\t\t\ttransportVal.fragmentOffset = msg.offset / 8;\n\t\t\ttransportVal.fragmentID = fragID;\n\t\t\ttransportVal.payloadType = CW_PACKET_PLAIN;\n\n\t\t\tif (i < ((*fragmentsNumPtr) - 1)) {\t// not last fragment\n\t\t\t\tfragSize = PMTU;\n\t\t\t\ttransportVal.last = 0;\n\t\t\t} else {\t// last fragment\n\t\t\t\tfragSize = totalSize - (((*fragmentsNumPtr) - 1) * PMTU);\n\t\t\t\ttransportVal.last = 1;\n\t\t\t}\n\n\t\t\tCWDebugLog(\"Fragment #:%d, offset:%d, bytes stored:%d/%d\", i, transportVal.fragmentOffset, fragSize, totalSize);\n\n\t\t\t// Assemble Transport Header for this fragment\n\t\t\tif (!(CWAssembleTransportHeader(&transportHdr, &transportVal))) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t}\n\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(((*completeMsgPtr)[i]), transportHdr.offset + fragSize,\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tCWProtocolStoreMessage(&((*completeMsgPtr)[i]), &transportHdr);\n\t\t\tCWProtocolStoreRawBytes(&((*completeMsgPtr)[i]), &((msg.msg)[msg.offset]), fragSize);\n\t\t\tmsg.offset += fragSize;\n\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(transportHdr);\n\t\t}\n\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t}\n\n\treturn CW_TRUE;\n}\n\nvoid CWProtocolDestroyFragment(void *f)\n{\n\tCW_FREE_OBJECT(((CWProtocolFragment *) f)->data);\n\tCW_FREE_OBJECT(f);\n}\n\nCWBool CWCompareFragment(void *newFrag, void *oldFrag)\n{\n\tCWProtocolFragment *newEl = (CWProtocolFragment *) newFrag;\n\tCWProtocolFragment *oldEl = (CWProtocolFragment *) oldFrag;\n\n\tif ((newEl->transportVal.fragmentID == oldEl->transportVal.fragmentID) &&\n\t    (newEl->transportVal.fragmentOffset == oldEl->transportVal.fragmentOffset)) {\n\t\treturn CW_TRUE;\n\t}\n\n\treturn CW_FALSE;\n}\n\n// parse a sigle fragment. If it is the last fragment we need or the only fragment, return the reassembled message in\n// *reassembleMsg. If we need at lest one more fragment, save this fragment in the list. You then call this function again\n// with a new fragment and the same list untill we got all the fragments.\nCWBool CWProtocolParseFragment(unsigned char *buf, int readBytes, CWList * fragmentsListPtr, CWProtocolMessage * reassembledMsg,\n\t\t\t       CWBool * dataFlagPtr, unsigned char *RadioMAC)\n{\n\n\tCWProtocolTransportHeaderValues values;\n\tCWProtocolMessage msg;\n\tint totalSize;\n\n\tmsg.msg = buf;\n\tmsg.offset = 0;\n\n\tif (!CWParseTransportHeader(&msg, &values, dataFlagPtr, RadioMAC)) {\n\t\tCWDebugLog(\"CWParseTransportHeader failed\");\n\t\treturn CW_FALSE;\n\t}\n\tif (values.isFragment == 0) {\t// single fragment\n\n\t\t/*  if(*fragmentsListPtr != NULL) { // we are receiving another fragmented message,\n\t\t   return CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Received Fragment with Different ID\"); // discard this packet\n\t\t   }\n\t\t */\n\t\tCW_CREATE_PROTOCOL_MESSAGE(*reassembledMsg, (readBytes - msg.offset),\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tCWProtocolStoreRawBytes(reassembledMsg, &(buf[msg.offset]), (readBytes - msg.offset));\n\t\treassembledMsg->data_msgType = msg.data_msgType;\n\t\treturn CW_TRUE;\n\t} else {\n\t\tCWListElement *el;\n\t\tCWProtocolFragment *fragPtr;\n\t\tint currentSize;\n\n\t\tCW_CREATE_OBJECT_ERR(fragPtr, CWProtocolFragment, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tfragPtr->transportVal.fragmentID = values.fragmentID;\n\t\tfragPtr->transportVal.fragmentOffset = values.fragmentOffset;\n\t\tfragPtr->transportVal.last = values.last;\n\n\t\tCWDebugLog(\"Received Fragment ID:%d, offset:%d, notLast:%d\", fragPtr->transportVal.fragmentID,\n\t\t\t   fragPtr->transportVal.fragmentOffset, fragPtr->transportVal.last);\n\n\t\tfragPtr->dataLen = (readBytes - msg.offset);\n\n\t\tif (*fragmentsListPtr == NULL ||\t// empty list\n\t\t    (((CWProtocolFragment *) ((*fragmentsListPtr)->data))->transportVal.fragmentID) == fragPtr->transportVal.fragmentID)\t// this fragment is in the set of fragments we are receiving\n\t\t\t/*      {\n\t\t\t   CW_CREATE_OBJECT_SIZE_ERR(fragPtr->data, fragPtr->dataLen, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\t\t\t   CW_COPY_MEMORY(fragPtr->data, &(buf[msg.offset]), fragPtr->dataLen);\n\n\t\t\t   if(!CWAddElementToList(fragmentsListPtr, fragPtr)) {\n\t\t\t   CWDeleteList(fragmentsListPtr, CWProtocolDestroyFragment);\n\t\t\t   CW_FREE_OBJECT(fragPtr);\n\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t   }\n\t\t\t   } */\n\t\t{\n\t\t\tCWListElement *aux = NULL;\n\t\t\taux = CWSearchInList(*fragmentsListPtr, fragPtr, CWCompareFragment);\n\t\t\tif (aux == NULL) {\n\t\t\t\tCW_CREATE_OBJECT_SIZE_ERR(fragPtr->data, fragPtr->dataLen,\n\t\t\t\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\tCW_COPY_MEMORY(fragPtr->data, &(buf[msg.offset]), fragPtr->dataLen);\n\n\t\t\t\tif (!CWAddElementToList(fragmentsListPtr, fragPtr)) {\n\t\t\t\t\tCWDeleteList(fragmentsListPtr, CWProtocolDestroyFragment);\n\t\t\t\t\tCW_FREE_OBJECT(fragPtr);\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tCWDebugLog(\"Received a copy of a fragment already in List\");\n\t\t\t\tCW_FREE_OBJECT(fragPtr);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, NULL);\n\t\t\t}\n\t\t} else {\n\t\t\tCWDebugLog(\"Discarded old fragments for different fragment ID: %d Vs %d\",\n\t\t\t\t   fragPtr->transportVal.fragmentID,\n\t\t\t\t   (((CWProtocolFragment *) ((*fragmentsListPtr)->data))->transportVal).fragmentID);\n\t\t\tCWDeleteList(fragmentsListPtr, CWProtocolDestroyFragment);\n\t\t\tCW_CREATE_OBJECT_SIZE_ERR(fragPtr->data, fragPtr->dataLen,\n\t\t\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tCW_COPY_MEMORY(fragPtr->data, &(buf[msg.offset]), fragPtr->dataLen);\n\t\t\tif (!CWAddElementToList(fragmentsListPtr, fragPtr)) {\n\t\t\t\tCWDeleteList(fragmentsListPtr, CWProtocolDestroyFragment);\n\t\t\t\tCW_FREE_OBJECT(fragPtr);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t}\n\t\t}\n\n\t\t// check if we have all the fragments\n\t\tfor (el = *fragmentsListPtr, totalSize = 0; el != NULL; el = el->next) {\n\t\t\tif ((((CWProtocolFragment *) (el->data))->transportVal.last) == 1) {\t// last element\n\t\t\t\ttotalSize = (((CWProtocolFragment *) (el->data))->transportVal.fragmentOffset) * 8;\n\t\t\t\ttotalSize += (((CWProtocolFragment *) (el->data))->dataLen);\n\t\t\t}\n\t\t}\n\n\t\tif (totalSize == 0) {\t// we haven't the last fragment\n\t\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, NULL);\t// we need at least one more fragment\n\t\t}\n\t\t// calculate the size of all the fragments we have so far\n\t\tfor (el = *fragmentsListPtr, currentSize = 0; el != NULL; el = el->next) {\n\t\t\tcurrentSize += (((CWProtocolFragment *) (el->data))->dataLen);\n\t\t\t//CWDebugLog(\"size %d/%d\", currentSize, totalSize);\n\t\t}\n\n\t\tCWDebugLog(\"totalSize = %d , currentSize = %d\", totalSize, currentSize);\n\n\t\tif (currentSize != totalSize) {\n\t\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, NULL);\t// we need at least one mpre fragment\n\t\t} else {\n\t\t\tint currentOffset = 0;\n\n\t\t\tCWLog(\"_______________________\");\n\t\t\tCWDebugLog(\"Received All Fragments\");\n\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*reassembledMsg, (totalSize),\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\n\t\t\tCW_REPEAT_FOREVER {\n\t\t\t\tCWBool found = CW_FALSE;\n\n\t\t\t\t// find the fragment in the list with the currend offset\n\t\t\t\tfor (el = *fragmentsListPtr, currentSize = 0; el != NULL; el = el->next) {\n\t\t\t\t\tif ((((CWProtocolFragment *) (el->data))->transportVal.fragmentOffset) ==\n\t\t\t\t\t    currentOffset) {\n\t\t\t\t\t\tfound = CW_TRUE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!found) {\t// mmm... we should have all the fragment, but we haven't a fragment for the current offset\n\t\t\t\t\tCWDeleteList(fragmentsListPtr, CWProtocolDestroyFragment);\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*reassembledMsg);\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Bad Fragmented Messsage\");\n\t\t\t\t}\n\n\t\t\t\tCWProtocolStoreRawBytes(reassembledMsg, (((CWProtocolFragment *) (el->data))->data),\n\t\t\t\t\t\t\t(((CWProtocolFragment *) (el->data))->dataLen));\n\t\t\t\treassembledMsg->data_msgType = msg.data_msgType;\n\n\t\t\t\tif ((((CWProtocolFragment *) (el->data))->transportVal.last) == 1) {\t// last fragment\n\t\t\t\t\tCWDebugLog(\"Message Reassembled\");\n\n\t\t\t\t\tCWDeleteList(fragmentsListPtr, CWProtocolDestroyFragment);\n\t\t\t\t\treturn CW_TRUE;\n\t\t\t\t}\n\n\t\t\t\tcurrentOffset += ((((CWProtocolFragment *) (el->data))->dataLen) / 8);\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Parse Transport Header\nCWBool CWParseTransportHeader(CWProtocolMessage * msgPtr, CWProtocolTransportHeaderValues * valuesPtr,\n\t\t\t      CWBool * dataFlagPtr, unsigned char *RadioMAC)\n{\n\n\tint transport4BytesLen;\n\tint val;\n\tint optionalWireless = 0;\n\tint version, rid;\n\tint m = 0;\n\n\tif (msgPtr == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t//CWDebugLog(\"Parse Transport Header\");\n\tval = CWProtocolRetrieve32(msgPtr);\n\n\tif (CWGetField32(val, CW_TRANSPORT_HEADER_VERSION_START, CW_TRANSPORT_HEADER_VERSION_LEN) !=\n\t    CW_PROTOCOL_VERSION)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Wrong Protocol Version\");\n\n\tversion = CWGetField32(val, CW_TRANSPORT_HEADER_VERSION_START, CW_TRANSPORT_HEADER_VERSION_LEN);\n\t//CWDebugLog(\"VERSION: %d\", version);\n\n\tvaluesPtr->payloadType = CWGetField32(val, CW_TRANSPORT_HEADER_TYPE_START, CW_TRANSPORT_HEADER_TYPE_LEN);\n\t//CWDebugLog(\"PAYLOAD TYPE: %d\", valuesPtr->payloadType);\n\n\ttransport4BytesLen = CWGetField32(val, CW_TRANSPORT_HEADER_HLEN_START, CW_TRANSPORT_HEADER_HLEN_LEN);\n\tCWDebugLog(\"HLEN: %d\", transport4BytesLen);\n\n\trid = CWGetField32(val, CW_TRANSPORT_HEADER_RID_START, CW_TRANSPORT_HEADER_RID_LEN);\n\tCWDebugLog(\"RID: %d\", rid);\n\n\tCWDebugLog(\"WBID: %d\", CWGetField32(val, CW_TRANSPORT_HEADER_WBID_START, CW_TRANSPORT_HEADER_WBID_LEN));\n\n\tvaluesPtr->type = CWGetField32(val, CW_TRANSPORT_HEADER_T_START, CW_TRANSPORT_HEADER_T_LEN);\n\tCWDebugLog(\"TYPE: %d\", valuesPtr->type);\n\t//CWDebugLog(\"TYPE: %d\", valuesPtr->type);\n\n\tvaluesPtr->isFragment = CWGetField32(val, CW_TRANSPORT_HEADER_F_START, CW_TRANSPORT_HEADER_F_LEN);\n\t//CWDebugLog(\"IS FRAGMENT: %d\", valuesPtr->isFragment);\n\n\tvaluesPtr->last = CWGetField32(val, CW_TRANSPORT_HEADER_L_START, CW_TRANSPORT_HEADER_L_LEN);\n\t//CWDebugLog(\"NOT LAST: %d\", valuesPtr->last);\n\n\toptionalWireless = CWGetField32(val, CW_TRANSPORT_HEADER_W_START, CW_TRANSPORT_HEADER_W_LEN);\n//  CWDebugLog(\"OPTIONAL WIRELESS: %d\", optionalWireless);\n\tm = CWGetField32(val, CW_TRANSPORT_HEADER_M_START, CW_TRANSPORT_HEADER_M_LEN);\n\n\tvaluesPtr->keepAlive = CWGetField32(val, CW_TRANSPORT_HEADER_K_START, CW_TRANSPORT_HEADER_K_LEN);\n//  CWDebugLog(\"KEEP ALIVE: %d\", valuesPtr->keepAlive);\n\n\tval = CWProtocolRetrieve32(msgPtr);\n\n\tvaluesPtr->fragmentID =\n\t    CWGetField32(val, CW_TRANSPORT_HEADER_FRAGMENT_ID_START, CW_TRANSPORT_HEADER_FRAGMENT_ID_LEN);\n//  CWDebugLog(\"FRAGMENT_ID: %d\", valuesPtr->fragmentID);\n\n\tvaluesPtr->fragmentOffset =\n\t    CWGetField32(val, CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_START, CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_LEN);\n//  CWDebugLog(\"FRAGMENT_OFFSET: %d\", valuesPtr->fragmentOffset);\n\n\tvaluesPtr->bindingValuesPtr = NULL;\n\n\tif (*dataFlagPtr == CW_TRUE) {\n\t\tif (valuesPtr->keepAlive) {\t// Keep Alive packet\n\t\t\tCWDebugLog(\"Keep-Alive packet\");\n\t\t\tmsgPtr->data_msgType = CW_DATA_MSG_KEEP_ALIVE_TYPE;\n\t\t} else if (valuesPtr->type == 0) {\t//IEEE 802.3 frame\n\t\t\tCWDebugLog(\"802.3 frame\");\n\t\t\tif (optionalWireless) {\n\t\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->bindingValuesPtr, CWBindingTransportHeaderValues,\n\t\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\tif (!CWParseTransportHeaderBinding(msgPtr, valuesPtr->bindingValuesPtr)) {\n\t\t\t\t\tCW_FREE_OBJECT(valuesPtr->bindingValuesPtr);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmsgPtr->data_msgType = CW_IEEE_802_3_FRAME_TYPE;\n\n\t\t} else if (valuesPtr->type == 1) {\t//IEEE 802.11 frame\n\t\t\tCWDebugLog(\"802.11 frame\");\n\t\t\tif (optionalWireless) {\n\t\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->bindingValuesPtr, CWBindingTransportHeaderValues,\n\t\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\tif (!CWParseTransportHeaderBinding(msgPtr, valuesPtr->bindingValuesPtr)) {\n\t\t\t\t\tCW_FREE_OBJECT(valuesPtr->bindingValuesPtr);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmsgPtr->data_msgType = CW_IEEE_802_11_FRAME_TYPE;\n\t\t} else {\n\t\t\tCWLog(\"Todo: This should be a keep-alive data packet!!!!\");\n\t\t}\n\t\tif (m) {\n\t\t\t//CW_CREATE_OBJECT_ERR( valuesPtr->MACValuesPtr, CWMACTransportHeaderValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY,NULL););\n\n\t\t\tif (!CWParseTransportHeaderMACAddress(msgPtr, RadioMAC)) {\n\t\t\t\t//CW_FREE_OBJECT(valuesPtr->bindingValuesPtr);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tif (transport4BytesLen == 4 && optionalWireless == 1) {\n\t\t\t*dataFlagPtr = CW_TRUE;\n\t\t\tCW_CREATE_OBJECT_ERR(valuesPtr->bindingValuesPtr, CWBindingTransportHeaderValues,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tif (!CWParseTransportHeaderBinding(msgPtr, valuesPtr->bindingValuesPtr)) {\n\t\t\t\tCW_FREE_OBJECT(valuesPtr->bindingValuesPtr);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t} else if (m) {\n\t\t\t//CW_CREATE_OBJECT_ERR( valuesPtr->MACValuesPtr, CWMACTransportHeaderValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY,NULL););\n\n\t\t\tif (!CWParseTransportHeaderMACAddress(msgPtr, RadioMAC)) {\n\t\t\t\t//CW_FREE_OBJECT(valuesPtr->bindingValuesPtr);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t}\n\t}\n\n\tCWDebugLog(NULL);\n\n\treturn (transport4BytesLen == 2 || (transport4BytesLen == 4 && optionalWireless == 1) || m) ? CW_TRUE : CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Malformed Transport Header\");\t//TEMP?\n}\n\n// Parse Control Header\nCWBool CWParseControlHeader(CWProtocolMessage * msgPtr, CWControlHeaderValues * valPtr)\n{\n\tif (msgPtr == NULL || valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n//  CWDebugLog(\"Parse Control Header\");\n\tvalPtr->messageTypeValue = CWProtocolRetrieve32(msgPtr);\n//  CWDebugLog(\"MESSAGE_TYPE: %u\",  valPtr->messageTypeValue);\n\n\tvalPtr->seqNum = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"SEQUENCE_NUMBER: %u\", valPtr->seqNum );\n\n\tvalPtr->msgElemsLen = CWProtocolRetrieve16(msgPtr);\n//  CWDebugLog(\"MESSAGE_ELEMENT_LENGTH: %u\", valPtr->msgElemsLen );\n\n\tCWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"FLAGS: %u\", flags);\n\n//  valPtr->timestamp = CWProtocolRetrieve32(msgPtr);\n//  CWDebugLog(\"TIME_STAMP: %u\",    valPtr->timestamp);\n\n\tCWDebugLog(NULL);\n\n\treturn CW_TRUE;\n}\n\n//## Assemble a Message Response containing a Failure (Unrecognized Message) Result Code\nCWBool CWAssembleUnrecognizedMessageResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU,\n\t\t\t\t\t     int seqNum, int msgType)\n{\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 1;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tint msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Unrecognized Message Response...\");\n\n\tCW_CREATE_OBJECT_ERR(msgElems, CWProtocolMessage, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!(CWAssembleMsgElemResultCode(msgElems, CW_PROTOCOL_FAILURE_UNRECOGNIZED_REQ))) {\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!\n\t    (CWAssembleMessage\n\t     (messagesPtr, fragmentsNumPtr, PMTU, seqNum, msgType, msgElems, msgElemCount, msgElemsBinding,\n\t      msgElemBindingCount)))\n\t    return CW_FALSE;\n\n\tCWLog(\"Unrecognized Message Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemSessionID(CWProtocolMessage * msgPtr, unsigned char *sessionID)\n{\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 16, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStoreRawBytes(msgPtr, sessionID, 16);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_SESSION_ID_CW_TYPE);\n}\n\nCWBool CWParseACName(CWProtocolMessage * msgPtr, int len, char **valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*valPtr = CWProtocolRetrieveStr(msgPtr, len);\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n//  CWDebugLog(\"AC Name:%s\", *valPtr);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPRadioAdminState(CWProtocolMessage * msgPtr, int len, CWRadioAdminInfoValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->ID = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->state = CWProtocolRetrieve8(msgPtr);\n\t//valPtr->cause = CWProtocolRetrieve8(msgPtr);\n\n//  CWDebugLog(\"WTP Radio Admin State: %d - %d - %d\", valPtr->ID, valPtr->state, valPtr->cause);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPRadioOperationalState(CWProtocolMessage * msgPtr, int len, CWRadioOperationalInfoValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->ID = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->state = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->cause = CWProtocolRetrieve8(msgPtr);\n\n        CWDebugLog(\"WTP Radio Operational State: %d - %d - %d\", valPtr->ID, valPtr->state, valPtr->cause);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseFormatMsgElem(CWProtocolMessage * completeMsg, unsigned short int *type, unsigned short int *len)\n{\n\t*type = CWProtocolRetrieve16(completeMsg);\n\t*len = CWProtocolRetrieve16(completeMsg);\n\treturn CW_TRUE;\n}\n\nCWBool CWParseResultCode(CWProtocolMessage * msgPtr, int len, CWProtocolResultCode * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*valPtr = CWProtocolRetrieve32(msgPtr);\n//  CWDebugLog(\"Result Code: %d\",   *valPtr);\n\n\tCWParseMessageElementEnd();\n}\n\nvoid CWWTPResetRadioStatistics(WTPRadioStatisticsInfo * radioStatistics)\n{\n\tradioStatistics->lastFailureType = UNKNOWN_TYPE;\n\tradioStatistics->resetCount = 0;\n\tradioStatistics->SWFailureCount = 0;\n\tradioStatistics->HWFailuireCount = 0;\n\tradioStatistics->otherFailureCount = 0;\n\tradioStatistics->unknownFailureCount = 0;\n\tradioStatistics->configUpdateCount = 0;\n\tradioStatistics->channelChangeCount = 0;\n\tradioStatistics->bandChangeCount = 0;\n\tradioStatistics->currentNoiseFloor = 0;\n}\n\nvoid CWFreeMessageFragments(CWProtocolMessage * messages, int fragmentsNum)\n{\n\tint i;\n\n\tfor (i = 0; i < fragmentsNum; i++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t}\n}\n\nunsigned char *CWParseSessionID(CWProtocolMessage * msgPtr, int len)\n{\n\treturn CWProtocolRetrieveRawBytes(msgPtr, 16);\n}\n"
  },
  {
    "path": "CWProtocol.h",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#ifndef __CAPWAP_CWProtocol_HEADER__\n#define __CAPWAP_CWProtocol_HEADER__\n\n//#define CWSetField32(obj, start, val) ((obj)[start/64]) |= ((val) << (start%64))\n//#define CWGetField32(obj, start, len) (((obj)[start/64]) & ((0xFFFFFFFFFFFFFFFF >> (64-(len))) << (start%64)) ) >> (start%64)\n\n/*_____________________________________________________*/\n/*  *******************___MACRO___*******************  */\n//#define CWSetField32(obj, start, val)                 ((obj)[start/32]) |= ((val) << (start%32))\n//#define CWGetField32(obj, start, len)                 (((obj)[start/32]) & ((0xFFFFFFFFUL >> (32-(len))) << (start%32)) ) >> (start%32)\n\n#define CWSetField32(src,start,len,val)                 src |= ((~(0xFFFFFFFF << len)) & val) << (32 - start - len)\n#define CWGetField32(src,start,len)                 ((~(0xFFFFFFFF<<len)) & (src >> (32 - start - len)))\n\n#define CW_REWIND_BYTES(buf, bytes, type)               (buf) = (type*)(((char*) (buf)) - bytes)\n#define CW_SKIP_BYTES(buf, bytes, type)                 (buf) = (type*)(((char*) (buf)) + bytes)\n#define CW_SKIP_BITS(buf, bits, type)                   (buf) = (type*)(((char*) (buf)) + ((bits) / 8))\n#define CW_BYTES_TO_STORE_BITS(bits)                    ((((bits) % 8) == 0) ? ((bits) / 8) : (((bits) / 8)+1))\n\n#define     CW_CREATE_PROTOCOL_MESSAGE(mess, size, err)     CW_CREATE_OBJECT_SIZE_ERR(((mess).msg), (size), err);       \\\n                                    CW_ZERO_MEMORY(((mess).msg), (size));                       \\\n                                    (mess).offset = 0;\n\n#define     CW_CREATE_PROTOCOL_MSG_ARRAY_ERR(ar_name, ar_size, on_err)  {\\\n                                            CW_CREATE_ARRAY_ERR(ar_name, ar_size, CWProtocolMessage, on_err)\\\n                                            int i;\\\n                                            for(i=0;i<(ar_size); i++) {\\\n                                                (ar_name)[i].msg = NULL;\\\n                                                (ar_name)[i].offset = 0; \\\n                                            }\\\n                                        }\n\n#define     CW_FREE_PROTOCOL_MESSAGE(mess)              CW_FREE_OBJECT(((mess).msg));                               \\\n                                    (mess).offset = 0;\n\n#define     CWParseMessageElementStart()                int oldOffset;                                              \\\n                                    if(msgPtr == NULL || valPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); \\\n                                    oldOffset = msgPtr->offset\n\n#define     CWParseMessageElementEnd()              CWDebugLog(NULL);                                           \\\n                                    return ((msgPtr->offset) - oldOffset) == len ? CW_TRUE :    \\\n                                    CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message Element Malformed\");\n\n/*_________________________________________________________*/\n/*  *******************___CONSTANTS___*******************  */\n\n// to be defined\n#define         MAX_UDP_PACKET_SIZE                 65536\n#define     CW_CONTROL_PORT                     5246\n#define     CW_DATA_PORT                        5247\n#define     CW_PROTOCOL_VERSION                 0\n#define     CW_IANA_ENTERPRISE_NUMBER               13277\n#define     CW_IANA_ENTERPRISE_NUMBER_VENDOR_IANA           18357\n#define     CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS          3\t//Offset \"Seq Num\" - \"Message Elements\"\n#define     CW_MAX_SEQ_NUM                      255\n#define     CW_MAX_FRAGMENT_ID                  65535\n#define     CLEAR_DATA                      1\n#define     DTLS_ENABLED_DATA                   2\n#define     CW_PACKET_PLAIN                     0\n#define     CW_PACKET_CRYPT                     1\n#define     CW_DATA_MSG_FRAME_TYPE                  1\n#define     CW_DATA_MSG_STATS_TYPE                  2\n#define     CW_DATA_MSG_FREQ_STATS_TYPE             3\t/* 2009 Update */\n#define         CW_IEEE_802_3_FRAME_TYPE                4\n#define         CW_DATA_MSG_KEEP_ALIVE_TYPE             5\n\n#define         CW_IEEE_802_11_FRAME_TYPE               6\n\n// <TRANSPORT_HEADER_FIELDS>\n// CAPWAP version (currently 0)\n#define     CW_TRANSPORT_HEADER_VERSION_START           0\n#define     CW_TRANSPORT_HEADER_VERSION_LEN             4\n\n// Mauro\n#define     CW_TRANSPORT_HEADER_TYPE_START              4\n#define     CW_TRANSPORT_HEADER_TYPE_LEN                4\n\n// Radio ID number (for WTPs with multiple radios)\n#define     CW_TRANSPORT_HEADER_RID_START               13\n#define     CW_TRANSPORT_HEADER_RID_LEN             5\n\n// Length of CAPWAP tunnel header in 4 byte words\n#define     CW_TRANSPORT_HEADER_HLEN_START              8\n#define     CW_TRANSPORT_HEADER_HLEN_LEN                5\n\n// Wireless Binding ID\n#define     CW_TRANSPORT_HEADER_WBID_START              18\n#define     CW_TRANSPORT_HEADER_WBID_LEN                5\n\n// Format of the frame\n#define     CW_TRANSPORT_HEADER_T_START             23\n#define     CW_TRANSPORT_HEADER_T_LEN               1\n\n// Is a fragment?\n#define     CW_TRANSPORT_HEADER_F_START             24\n#define     CW_TRANSPORT_HEADER_F_LEN               1\n\n// Is NOT the last fragment?\n#define     CW_TRANSPORT_HEADER_L_START             25\n#define     CW_TRANSPORT_HEADER_L_LEN               1\n\n// Is the Wireless optional header present?\n#define     CW_TRANSPORT_HEADER_W_START             26\n#define     CW_TRANSPORT_HEADER_W_LEN               1\n\n// Is the Radio MAC Address optional field present?\n#define     CW_TRANSPORT_HEADER_M_START             27\n#define     CW_TRANSPORT_HEADER_M_LEN               1\n\n// Is the message a keep alive?\n#define     CW_TRANSPORT_HEADER_K_START             28\n#define     CW_TRANSPORT_HEADER_K_LEN               1\n\n// Set to 0 in this version of the protocol\n#define     CW_TRANSPORT_HEADER_FLAGS_START             29\n#define     CW_TRANSPORT_HEADER_FLAGS_LEN               3\n\n// ID of the group of fragments\n#define     CW_TRANSPORT_HEADER_FRAGMENT_ID_START           0\n#define     CW_TRANSPORT_HEADER_FRAGMENT_ID_LEN         16\n\n// Position of this fragment in the group\n#define     CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_START       16\n#define     CW_TRANSPORT_HEADER_FRAGMENT_OFFSET_LEN         13\n\n// Set to 0 in this version of the protocol\n#define     CW_TRANSPORT_HEADER_RESERVED_START          29\n#define     CW_TRANSPORT_HEADER_RESERVED_LEN            3\n// </TRANSPORT_HEADER_FIELDS>\n\n// Message Type Values\n#define     CW_MSG_TYPE_VALUE_DISCOVERY_REQUEST         1\n#define     CW_MSG_TYPE_VALUE_DISCOVERY_RESPONSE            2\n#define     CW_MSG_TYPE_VALUE_JOIN_REQUEST              3\n#define     CW_MSG_TYPE_VALUE_JOIN_RESPONSE             4\n#define     CW_MSG_TYPE_VALUE_CONFIGURE_REQUEST         5\n#define     CW_MSG_TYPE_VALUE_CONFIGURE_RESPONSE            6\n#define     CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_REQUEST      7\n#define     CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE     8\n#define     CW_MSG_TYPE_VALUE_WTP_EVENT_REQUEST         9\n#define     CW_MSG_TYPE_VALUE_WTP_EVENT_RESPONSE            10\n#define     CW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_REQUEST        11\n#define     CW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_RESPONSE       12\n#define     CW_MSG_TYPE_VALUE_ECHO_REQUEST              13\n#define     CW_MSG_TYPE_VALUE_ECHO_RESPONSE             14\n#define     CW_MSG_TYPE_VALUE_IMAGE_DATA_REQUEST            15\n#define     CW_MSG_TYPE_VALUE_IMAGE_DATA_RESPONSE           16\n#define     CW_MSG_TYPE_VALUE_RESET_REQUEST             17\n#define     CW_MSG_TYPE_VALUE_RESET_RESPONSE            18\n#define     CW_MSG_TYPE_VALUE_PRIMARY_DISCOVERY_REQUEST     19\n#define     CW_MSG_TYPE_VALUE_PRIMARY_DISCOVERY_RESPONSE        20\n#define     CW_MSG_TYPE_VALUE_DATA_TRANSFER_REQUEST         21\n#define     CW_MSG_TYPE_VALUE_DATA_TRANSFER_RESPONSE        22\n#define     CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_REQUEST       23\n#define     CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_RESPONSE      24\n#define     CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_REQUEST     25\n#define     CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE    26\n\n// IEEE 802.11 Binding Type\n#define     CW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_REQUEST        3398913\n#define     CW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_RESPONSE       3398914\n\n// Message Elements Type Values\n#define     CW_MSG_ELEMENT_AC_DESCRIPTOR_CW_TYPE            1\n#define     CW_MSG_ELEMENT_AC_IPV4_LIST_CW_TYPE         2\n#define     CW_MSG_ELEMENT_AC_IPV6_LIST_CW_TYPE         3\n#define     CW_MSG_ELEMENT_AC_NAME_CW_TYPE              4\n#define     CW_MSG_ELEMENT_AC_NAME_INDEX_CW_TYPE            5\n#define     CW_MSG_ELEMENT_TIMESTAMP_CW_TYPE            6\n#define     CW_MSG_ELEMENT_ADD_MAC_ACL_CW_TYPE          7\n#define     CW_MSG_ELEMENT_ADD_STATION_CW_TYPE          8\n#define     CW_MSG_ELEMENT_ADD_STATIC_MAC_ACL_CW_TYPE       9\n#define     CW_MSG_ELEMENT_CW_CONTROL_IPV4_ADDRESS_CW_TYPE      10\n#define     CW_MSG_ELEMENT_CW_CONTROL_IPV6_ADDRESS_CW_TYPE      11\n#define     CW_MSG_ELEMENT_CW_TIMERS_CW_TYPE            12\n#define     CW_MSG_ELEMENT_DATA_TRANSFER_DATA_CW_TYPE       13\n#define     CW_MSG_ELEMENT_DATA_TRANSFER_MODE_CW_TYPE       14\n#define     CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_CW_TYPE     15\n#define     CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_PERIOD_CW_TYPE  16\n#define     CW_MSG_ELEMENT_DELETE_MAC_ACL_CW_TYPE           17\n#define     CW_MSG_ELEMENT_DELETE_STATION_CW_TYPE           18\n#define     CW_MSG_ELEMENT_DELETE_STATIC_MAC_ACL_CW_TYPE        19\n#define     CW_MSG_ELEMENT_DISCOVERY_TYPE_CW_TYPE           20\n#define     CW_MSG_ELEMENT_DUPLICATE_IPV4_ADDRESS_CW_TYPE       21\n#define     CW_MSG_ELEMENT_DUPLICATE_IPV6_ADDRESS_CW_TYPE       22\n#define     CW_MSG_ELEMENT_IDLE_TIMEOUT_CW_TYPE         23\n#define     CW_MSG_ELEMENT_IMAGE_DATA_CW_TYPE           24\n#define     CW_MSG_ELEMENT_IMAGE_IDENTIFIER_CW_TYPE         25\n#define     CW_MSG_ELEMENT_IMAGE_INFO_CW_TYPE           26\n#define     CW_MSG_ELEMENT_INITIATED_DOWNLOAD_CW_TYPE       27\n#define     CW_MSG_ELEMENT_LOCATION_DATA_CW_TYPE            28\n#define     CW_MSG_ELEMENT_MAX_MSG_LEN_CW_TYPE          29\n#define     CW_MSG_ELEMENT_WTP_IPV4_ADDRESS_CW_TYPE         30\n#define     CW_MSG_ELEMENT_RADIO_ADMIN_STATE_CW_TYPE        31\n#define     CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE       32\n#define     CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE          33\n#define     CW_MSG_ELEMENT_RETURNED_MSG_ELEM_CW_TYPE        34\n#define     CW_MSG_ELEMENT_SESSION_ID_CW_TYPE           35\n#define     CW_MSG_ELEMENT_STATISTICS_TIMER_CW_TYPE         36\n#define     CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_BW_CW_TYPE       37\n#define     CW_MSG_ELEMENT_WTP_BOARD_DATA_CW_TYPE           38\n#define     CW_MSG_ELEMENT_WTP_DESCRIPTOR_CW_TYPE           39\n#define     CW_MSG_ELEMENT_WTP_FALLBACK_CW_TYPE         40\n#define     CW_MSG_ELEMENT_WTP_FRAME_TUNNEL_MODE_CW_TYPE        41\n#define     CW_MSG_ELEMENT_WTP_MAC_TYPE_CW_TYPE         44\n#define     CW_MSG_ELEMENT_WTP_NAME_CW_TYPE             45\n#define     CW_MSG_ELEMENT_WTP_OPERAT_STATISTICS_CW_TYPE        46\n#define     CW_MSG_ELEMENT_WTP_RADIO_STATISTICS_CW_TYPE     47\n#define     CW_MSG_ELEMENT_WTP_REBOOT_STATISTICS_CW_TYPE        48\n#define     CW_MSG_ELEMENT_WTP_STATIC_IP_CW_TYPE            49\n/*Update 2009:\n        Message type to return a payload together with the\n        configuration update response*/\n#define     CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE      57\n#define     CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE_WITH_PAYLOAD     58\n#define     CW_MSG_ELEMENT_MTU_DISCOVERY_PADDING_CW_TYPE        59\n\n//Vendor Specific data\n#define     CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_AC_PRIORITY      128\n#define     CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_AC_PRIORITY_LEN  1\n#define     CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_AC_PRIORITY_DEFAULT  3\n\n// IEEE 802.11 Message Element\n#define     CW_MSG_ELEMENT_IEEE80211_ADD_WLAN_CW_TYPE                       1024\n#define     CW_MSG_ELEMENT_IEEE80211_DELETE_WLAN_CW_TYPE                    1027\n#define     CW_MSG_ELEMENT_IEEE80211_MULTI_DOMAIN_CAPABILITY_CW_TYPE        1032\n#define     CW_MSG_ELEMENT_IEEE80211_SUPPORTED_RATES_CW_TYPE                1040\n#define     CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE          1048\n\n// CAPWAP Protocol Variables\n#define     CW_MAX_RETRANSMIT_DEFAULT       1\n#define     CW_WAIT_JOIN_DEFAULT            60\n#define     CW_REPORT_INTERVAL_DEFAULT      120\n#define     CW_STATISTIC_TIMER_DEFAULT      120\n\n#ifdef CW_DEBUGGING\n#define     CW_JOIN_INTERVAL_DEFAULT    60\n#else\n#define     CW_JOIN_INTERVAL_DEFAULT    60\n#endif\n\n#ifdef CW_DEBUGGING\n#define     CW_CHANGE_STATE_INTERVAL_DEFAULT 10\n#else\n#define     CW_CHANGE_STATE_INTERVAL_DEFAULT 25\n#endif\n\n#ifdef CW_DEBUGGING\n#define     CW_RETRANSMIT_INTERVAL_DEFAULT      10 \n#else\n#define     CW_RETRANSMIT_INTERVAL_DEFAULT      10 \n#endif\n\n#ifdef CW_DEBUGGING\n#define     CW_NEIGHBORDEAD_INTERVAL_DEFAULT    33 \n#define     CW_NEIGHBORDEAD_RESTART_DISCOVERY_DELTA_DEFAULT ((CW_NEIGHBORDEAD_INTERVAL_DEFAULT) + 40)\n#else\n#define     CW_NEIGHBORDEAD_INTERVAL_DEFAULT    33 \n#define     CW_NEIGHBORDEAD_RESTART_DISCOVERY_DELTA_DEFAULT ((CW_NEIGHBORDEAD_INTERVAL_DEFAULT) + 40)\n#endif\n\n#ifdef CW_DEBUGGING\n#define     CW_ECHO_INTERVAL_DEFAULT        30 \n#define     CW_DATA_CHANNEL_KEEP_ALIVE_DEFAULT  30\n#else\n#define     CW_ECHO_INTERVAL_DEFAULT        30\n#define     CW_DATA_CHANNEL_KEEP_ALIVE_DEFAULT  30\n#endif\n\n/*_________________________________________________________*/\n/*  *******************___VARIABLES___*******************  */\n\n/*_____________________________________________________*/\n/*  *******************___TYPES___*******************  */\ntypedef struct {\n\tint type;\n\tint value;\n} CWMsgElemData;\n\ntypedef unsigned char CWMACAddress[6];\n\ntypedef enum {\n\tCW_PROTOCOL_SUCCESS = 0,\t// Success\n\tCW_PROTOCOL_FAILURE_AC_LIST = 1,\t// AC List message MUST be present\n\tCW_PROTOCOL_SUCCESS_NAT = 2,\t// NAT detected\n\tCW_PROTOCOL_FAILURE = 3,\t// unspecified\n\tCW_PROTOCOL_FAILURE_RES_DEPLETION = 4,\t// Resource Depletion\n\tCW_PROTOCOL_FAILURE_UNKNOWN_SRC = 5,\t// Unknown Source\n\tCW_PROTOCOL_FAILURE_INCORRECT_DATA = 6,\t// Incorrect Data\n\tCW_PROTOCOL_FAILURE_ID_IN_USE = 7,\t// Session ID Alreadyin Use\n\tCW_PROTOCOL_FAILURE_WTP_HW_UNSUPP = 8,\t// WTP Hardware not supported\n\tCW_PROTOCOL_FAILURE_BINDING_UNSUPP = 9,\t// Binding not supported\n\tCW_PROTOCOL_FAILURE_UNABLE_TO_RESET = 10,\t// Unable to reset\n\tCW_PROTOCOL_FAILURE_FIRM_WRT_ERROR = 11,\t// Firmware write error\n\tCW_PROTOCOL_FAILURE_SERVICE_PROVIDED_ANYHOW = 12,\t// Unable to apply requested configuration\n\tCW_PROTOCOL_FAILURE_SERVICE_NOT_PROVIDED = 13,\t// Unable to apply requested configuration\n\tCW_PROTOCOL_FAILURE_INVALID_CHECKSUM = 14,\t// Image Data Error: invalid checksum\n\tCW_PROTOCOL_FAILURE_INVALID_DATA_LEN = 15,\t// Image Data Error: invalid data length\n\tCW_PROTOCOL_FAILURE_OTHER_ERROR = 16,\t// Image Data Error: other error\n\tCW_PROTOCOL_FAILURE_IMAGE_ALREADY_PRESENT = 17,\t// Image Data Error: image already present\n\tCW_PROTOCOL_FAILURE_INVALID_STATE = 18,\t// Message unexpected: invalid in current state\n\tCW_PROTOCOL_FAILURE_UNRECOGNIZED_REQ = 19,\t// Message unexpected: unrecognized request\n\tCW_PROTOCOL_FAILURE_MISSING_MSG_ELEM = 20,\t// Failure: missing mandatory message element\n\tCW_PROTOCOL_FAILURE_UNRECOGNIZED_MSG_ELEM = 21\t// Failure: unrecognized message element\n} CWProtocolResultCode;\n\ntypedef struct {\n\tunsigned char *msg;\n\tint offset;\n\tint data_msgType;\n} CWProtocolMessage;\n\n#define     MAX_PENDING_REQUEST_MSGS    15\n#define     UNUSED_MSG_TYPE         0\n\ntypedef struct {\n\tunsigned char msgType;\n\tunsigned char seqNum;\n\tint timer_sec;\n\tvoid (*timer_hdl) (void *);\n\tCWTimerArg timer_arg;\n\tCWTimerID timer;\n\tint retransmission;\n\tCWProtocolMessage *msgElems;\n\tint fragmentsNum;\n} CWPendingRequestMessage;\n\n#include \"CWBinding.h\"\n\ntypedef struct {\n\tint payloadType;\n\tint type;\n\tint isFragment;\n\tint last;\n\tint fragmentID;\n\tint fragmentOffset;\n\tint keepAlive;\n\tCWBindingTransportHeaderValues *bindingValuesPtr;\n} CWProtocolTransportHeaderValues;\n\ntypedef struct {\n\tunsigned int messageTypeValue;\n\tunsigned char seqNum;\n\tunsigned short msgElemsLen;\n//  unsigned int timestamp;\n} CWControlHeaderValues;\n\ntypedef struct {\n\tunsigned char *data;\n\tint dataLen;\n\tCWProtocolTransportHeaderValues transportVal;\n} CWProtocolFragment;\n\ntypedef struct {\n\tint vendorIdentifier;\n\tenum {\n\t\tCW_WTP_MODEL_NUMBER = 0,\n\t\tCW_WTP_SERIAL_NUMBER = 1,\n\t\tCW_BOARD_ID = 2,\n\t\tCW_BOARD_REVISION = 3,\n\n\t\tCW_WTP_HARDWARE_VERSION = 0,\n\t\tCW_WTP_SOFTWARE_VERSION = 1,\n\t\tCW_BOOT_VERSION = 2\n\t} type;\n\tint length;\n\tunsigned char *valuePtr;\n} CWWTPVendorInfoValues;\n\ntypedef struct {\n\tint vendorInfosCount;\n\tCWWTPVendorInfoValues *vendorInfos;\n} CWWTPVendorInfos;\n\ntypedef struct {\n\tunsigned short WBID;\n\tunsigned int encryptionCapabilities;\n} CWWTPEncryptCapValues;\n\ntypedef struct {\n\tint encryptCapsCount;\n\tCWWTPEncryptCapValues *encryptCaps;\n} CWWTPEncryptCaps;\n\ntypedef struct {\n\tint maxRadios;\n\tint radiosInUse;\n\tCWWTPEncryptCaps encCapabilities;\n\tCWWTPVendorInfos vendorInfos;\n} CWWTPDescriptor;\n\ntypedef enum {\n\tCW_RESERVE = 1,\n\tCW_LOCAL_BRIDGING = 2,\n\tCW_802_DOT_3_BRIDGING = 4,\n\tCW_NATIVE_BRIDGING = 8,\n\tCW_ALL_ENC = 15\n} CWframeTunnelMode;\n\ntypedef enum {\n\tCW_TUNNEL_MODE_LOCAL_BRIDGING = 0,\n\tCW_TUNNEL_MODE_802_DOT_3_TUNNEL = 1,\n\tCW_TUNNEL_MODE_802_DOT_11_TUNNEL = 2\n} CWTunnelMode;\n\ntypedef enum {\n\tCW_LOCAL_MAC = 0,\n\tCW_SPLIT_MAC = 1,\n\tCW_BOTH = 2\n} CWMACType;\n\ntypedef struct {\n\tenum {\n\t\tCW_MSG_ELEMENT_DISCOVERY_TYPE_BROADCAST = 0,\n\t\tCW_MSG_ELEMENT_DISCOVERY_TYPE_CONFIGURED = 1\n\t} type;\n\tCWWTPVendorInfos WTPBoardData;\n\tCWWTPDescriptor WTPDescriptor;\n\tCWframeTunnelMode frameTunnelMode;\n\tCWMACType MACType;\n\n} CWDiscoveryRequestValues;\n\ntypedef enum {\n\tCW_X509_CERTIFICATE = 2,\n\tCW_PRESHARED = 4\n} CWAuthSecurity;\n\ntypedef struct {\n\tCWNetworkLev4Address addr;\n\tstruct sockaddr_in addrIPv4;\n\n\tint WTPCount;\n} CWProtocolNetworkInterface;\n\ntypedef struct {\n\tint WTPCount;\n\tstruct sockaddr_in addr;\n} CWProtocolIPv4NetworkInterface;\n\ntypedef struct {\n\tint WTPCount;\n\tstruct sockaddr_in6 addr;\n} CWProtocolIPv6NetworkInterface;\n\ntypedef struct {\n\tint vendorIdentifier;\n\tenum {\n\t\tCW_AC_HARDWARE_VERSION = 4,\n\t\tCW_AC_SOFTWARE_VERSION = 5\n\t} type;\n\tint length;\n\tint *valuePtr;\n} CWACVendorInfoValues;\n\ntypedef struct {\n\tint vendorInfosCount;\n\tCWACVendorInfoValues *vendorInfos;\n} CWACVendorInfos;\n\ntypedef struct {\n\tint rebootCount;\n\tint ACInitiatedCount;\n\tint linkFailurerCount;\n\tint SWFailureCount;\n\tint HWFailuireCount;\n\tint otherFailureCount;\n\tint unknownFailureCount;\n\tenum {\n\t\tNOT_SUPPORTED = 0,\n\t\tAC_INITIATED = 1,\n\t\tLINK_FAILURE = 2,\n\t\tSW_FAILURE = 3,\n\t\tHD_FAILURE = 4,\n\t\tOTHER_FAILURE = 5,\n\t\tUNKNOWN = 255\n\t} lastFailureType;\n} WTPRebootStatisticsInfo;\n\ntypedef struct {\n\tint radioID;\n\tint reportInterval;\n} WTPDecryptErrorReportValues;\n\ntypedef struct {\n\tint radiosCount;\n\tWTPDecryptErrorReportValues *radios;\n} WTPDecryptErrorReport;\n\ntypedef struct {\n\tint index;\n\tchar *ACName;\n} CWACNameWithIndexValues;\n\ntypedef struct {\n\tint count;\n\tCWACNameWithIndexValues *ACNameIndex;\n} CWACNamesWithIndex;\n\ntypedef struct {\n\tint ID;\n\tenum {\n\t\tCW_802_DOT_11b = 1,\n\t\tCW_802_DOT_11a = 2,\n\t\tCW_802_DOT_11g = 4,\n\t\tCW_802_DOT_11n = 8,\n\t\tCW_ALL_RADIO_TYPES = 0x0F\n\t} type;\n} CWRadioInformationValues;\n\ntypedef struct {\n\tint radiosCount;\n\tCWRadioInformationValues *radios;\n} CWRadiosInformation;\n\ntypedef enum {\n\tENABLED = 1,\n\tDISABLED = 2\n} CWstate;\n\ntypedef enum {\n\tAD_NORMAL = 1,\n\tAD_RADIO_FAILURE = 2,\n\tAD_SOFTWARE_FAILURE = 3,\n\tAD_RADAR_DETECTION = 4\n} CWAdminCause;\n\ntypedef enum {\n\tOP_NORMAL = 0,\n\tOP_RADIO_FAILURE = 1,\n\tOP_SOFTWARE_FAILURE = 2,\n\tOP_ADMINISTRATIVELY_SET = 3\n} CWOperationalCause;\n\ntypedef struct {\n\tint ID;\n\tCWstate state;\n\tCWAdminCause cause;\n} CWRadioAdminInfoValues;\n\ntypedef struct {\n\tint radiosCount;\n\tCWRadioAdminInfoValues *radios;\n} CWRadiosAdminInfo;\n\ntypedef struct {\n\tint ID;\n\tCWstate state;\n\tCWOperationalCause cause;\n} CWRadioOperationalInfoValues;\n\ntypedef struct {\n\tint radiosCount;\n\tCWRadioOperationalInfoValues *radios;\n} CWRadiosOperationalInfo;\n\ntypedef struct {\n\tint ID;\n\tunsigned char numEntries;\n\tunsigned char length;\n\tCWMACAddress *decryptErrorMACAddressList;\n} CWDecryptErrorReportValues;\n\ntypedef struct {\n\tint radiosCount;\n\tCWDecryptErrorReportValues *radios;\n} CWDecryptErrorReportInfo;\n\ntypedef struct {\n\tenum {\n\t\tSTATISTICS_NOT_SUPPORTED = 0,\n\t\tSW_FAILURE_TYPE = 1,\n\t\tHD_FAILURE_TYPE = 2,\n\t\tOTHER_TYPES = 3,\n\t\tUNKNOWN_TYPE = 255\n\t} lastFailureType;\n\tshort int resetCount;\n\tshort int SWFailureCount;\n\tshort int HWFailuireCount;\n\tshort int otherFailureCount;\n\tshort int unknownFailureCount;\n\tshort int configUpdateCount;\n\tshort int channelChangeCount;\n\tshort int bandChangeCount;\n\tshort int currentNoiseFloor;\n} WTPRadioStatisticsInfo;\n\ntypedef struct {\n\tunsigned int radioID;\n\t//Station Mac Address List\n\n\tCWList decryptErrorMACAddressList;\n\n\tunsigned int reportInterval;\n\n\tCWstate adminState;\n\tCWAdminCause adminCause;\n\n\tCWstate operationalState;\n\tCWOperationalCause operationalCause;\n\n\tunsigned int TxQueueLevel;\n\tunsigned int wirelessLinkFramesPerSec;\n\n\tWTPRadioStatisticsInfo statistics;\n\n\tvoid *bindingValuesPtr;\n} CWWTPRadioInfoValues;\n\ntypedef struct {\n\tint radioCount;\n\tCWWTPRadioInfoValues *radiosInfo;\n} CWWTPRadiosInfo;\n\n/*Update 2009:\n    Helper structure to keep track of\n    requested UCI commands (via Vendor specific\n    message)*/\ntypedef struct {\n\tunsigned short vendorPayloadType;\n\tvoid *payload;\n} CWProtocolVendorSpecificValues;\n\n#include \"CWList.h\"\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\n\nunsigned int CWGetSeqNum();\t// provided by the user of CWProtocol lib\nint CWGetFragmentID();\t\t// provided by the user of CWProtocol lib\n\nvoid CWWTPResetRadioStatistics(WTPRadioStatisticsInfo * radioStatistics);\n\nvoid CWProtocolDestroyMsgElemData(void *f);\nvoid CWFreeMessageFragments(CWProtocolMessage * messages, int fragmentsNum);\n\nvoid CWProtocolStore8(CWProtocolMessage * msgPtr, unsigned char val);\nvoid CWProtocolStore16(CWProtocolMessage * msgPtr, unsigned short val);\nvoid CWProtocolStore32(CWProtocolMessage * msgPtr, unsigned int val);\nvoid CWProtocolStoreStr(CWProtocolMessage * msgPtr, char *str);\nvoid CWProtocolStoreMessage(CWProtocolMessage * msgPtr, CWProtocolMessage * msgToStorePtr);\nvoid CWProtocolStoreRawBytes(CWProtocolMessage * msgPtr, unsigned char *bytes, int len);\n\nunsigned char CWProtocolRetrieve8(CWProtocolMessage * msgPtr);\nunsigned short CWProtocolRetrieve16(CWProtocolMessage * msgPtr);\nunsigned int CWProtocolRetrieve32(CWProtocolMessage * msgPtr);\nchar *CWProtocolRetrieveStr(CWProtocolMessage * msgPtr, int len);\nunsigned char *CWProtocolRetrieveRawBytes(CWProtocolMessage * msgPtr, unsigned int len);\n\nCWBool CWProtocolParseFragment(unsigned char *buf, int readBytes, CWList * fragmentsListPtr, CWProtocolMessage * reassembledMsg,\n\t\t\t       CWBool * dataFlag, unsigned char *RadioMAC);\nvoid CWProtocolDestroyFragment(void *f);\n\nCWBool CWParseTransportHeader(CWProtocolMessage * msgPtr, CWProtocolTransportHeaderValues * valuesPtr,\n\t\t\t      CWBool * dataFlag, unsigned char *RadioMAC);\nCWBool CWParseControlHeader(CWProtocolMessage * msgPtr, CWControlHeaderValues * valPtr);\nCWBool CWParseFormatMsgElem(CWProtocolMessage * completeMsg, unsigned short int *type, unsigned short int *len);\n\nCWBool CWAssembleTransportHeader(CWProtocolMessage * transportHdrPtr, CWProtocolTransportHeaderValues * valuesPtr);\nCWBool CWAssembleTransportHeaderKeepAliveData(CWProtocolMessage * transportHdrPtr,\n\t\t\t\t\t      CWProtocolTransportHeaderValues * valuesPtr, int keepAlive);\nCWBool CWAssembleControlHeader(CWProtocolMessage * controlHdrPtr, CWControlHeaderValues * valPtr);\nCWBool CWAssembleMessage(CWProtocolMessage ** completeMsgPtr, int *fragmentsNumPtr, int PMTU, int seqNum,\n\t\t\t int msgTypeValue, CWProtocolMessage * msgElems, const int msgElemNum,\n\t\t\t CWProtocolMessage * msgElemsBinding, const int msgElemBindingNum);\nCWBool CWAssembleMsgElem(CWProtocolMessage * msgPtr, unsigned int type);\nCWBool CWAssembleUnrecognizedMessageResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU,\n\t\t\t\t\t     int seqNum, int msgType);\n\nCWBool CWAssembleMsgElemRadioAdminState(CWProtocolMessage * msgPtr);\t//29\nCWBool CWAssembleMsgElemRadioOperationalState(int radioID, CWProtocolMessage * msgPtr);\t//30\nCWBool CWAssembleMsgElemResultCode(CWProtocolMessage * msgPtr, CWProtocolResultCode code);\t//31\nCWBool CWAssembleVendorMsgElemResultCodeWithPayload(CWProtocolMessage * msgPtr, CWProtocolResultCode code, CWProtocolVendorSpecificValues * payload);\t//49\nCWBool CWAssembleMsgElemSessionID(CWProtocolMessage * msgPtr, unsigned char *sessionID);\t//32\n\nCWBool CWParseACName(CWProtocolMessage * msgPtr, int len, char **valPtr);\nCWBool CWParseWTPRadioOperationalState(CWProtocolMessage * msgPtr, int len, CWRadioOperationalInfoValues * valPtr);\t//30\nCWBool CWParseResultCode(CWProtocolMessage * msgPtr, int len, CWProtocolResultCode * valPtr);\t//31\nunsigned char *CWParseSessionID(CWProtocolMessage * msgPtr, int len);\n\n#endif\n"
  },
  {
    "path": "CWRandom.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n__inline__ void CWRandomInitLib()\n{\n\t// set seed\n\tsrand((unsigned)time(NULL));\n}\n\n__inline__ int CWRandomIntInRange(int min, int max)\n{\n\treturn min + (rand() % (max - min));\n}\n"
  },
  {
    "path": "CWRandom.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWRandom_HEADER__\n#define __CAPWAP_CWRandom_HEADER__\n\nvoid CWRandomInitLib();\nint CWRandomIntInRange(int min, int max);\n\n#endif\n"
  },
  {
    "path": "CWSafeList.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool CWCreateSafeList(CWSafeList * pSafeList)\n{\n\tCWPrivateSafeList *pNewList;\n\n\tif (pSafeList == NULL)\n\t\treturn CW_FALSE;\n\n\tCW_CREATE_OBJECT_ERR(pNewList, CWPrivateSafeList, return CW_FALSE;\n\t    );\n\n\t//\n\tpNewList->pThreadMutex = NULL;\n\tpNewList->pThreadCond = NULL;\n\n\t//\n\tpNewList->nCount = 0;\n\tpNewList->pFirstElement = NULL;\n\tpNewList->pLastElement = NULL;\n\n\t//\n\t(*pSafeList) = (CWSafeList) pNewList;\n\treturn CW_TRUE;\n}\n\nvoid CWDestroySafeList(CWSafeList safeList)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif (pList == NULL)\n\t\treturn;\n\n\t//\n\tCW_FREE_OBJECT(pList);\n}\n\nvoid CWSetMutexSafeList(CWSafeList safeList, CWThreadMutex * pThreadMutex)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif (pList == NULL)\n\t\treturn;\n\n\tpList->pThreadMutex = pThreadMutex;\n}\n\nvoid CWSetConditionSafeList(CWSafeList safeList, CWThreadCondition * pThreadCond)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif (pList == NULL)\n\t\treturn;\n\n\tpList->pThreadCond = pThreadCond;\n}\n\nCWBool CWLockSafeList(CWSafeList safeList)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif ((pList == NULL) || (pList->pThreadMutex == NULL))\n\t\treturn CW_FALSE;\n\n\t//\n\treturn CWThreadMutexLock(pList->pThreadMutex);\n}\n\nvoid CWUnlockSafeList(CWSafeList safeList)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif ((pList == NULL) || (pList->pThreadMutex == NULL))\n\t\treturn;\n\n\t//\n\tCWThreadMutexUnlock(pList->pThreadMutex);\n}\n\nCWBool CWWaitElementFromSafeList(CWSafeList safeList)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif ((pList == NULL) || (pList->pThreadMutex == NULL) || (pList->pThreadCond == NULL))\n\t\treturn CW_FALSE;\n\n\treturn CWWaitThreadCondition(pList->pThreadCond, pList->pThreadMutex);\n}\n\nCWBool CWSignalElementSafeList(CWSafeList safeList)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif ((pList == NULL) || (pList->pThreadCond == NULL))\n\t\treturn CW_FALSE;\n\n\tCWSignalThreadCondition(pList->pThreadCond);\n\treturn CW_TRUE;\n}\n\nunsigned long CWGetCountElementFromSafeList(CWSafeList safeList)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif (pList == NULL)\n\t\treturn 0;\n\treturn pList->nCount;\n\n}\n\n// No thread-safe\nCWBool CWAddElementToSafeListHead(CWSafeList safeList, void *pData, int nSize)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\tCWPrivateSafeElement *pNewElement;\n\n\tif ((pList == NULL) || (pData == NULL))\n\t\treturn CW_FALSE;\n\n\tCW_CREATE_OBJECT_ERR(pNewElement, CWPrivateSafeElement, return CW_FALSE;\n\t    );\n\tpNewElement->pData = pData;\n\tpNewElement->nSize = nSize;\n\tpNewElement->pNext = pList->pFirstElement;\n\tpNewElement->pPrev = NULL;\n\tif (pList->pFirstElement != NULL)\n\t\tpList->pFirstElement->pPrev = pNewElement;\n\n\tpList->pFirstElement = pNewElement;\n\tif (pList->pLastElement == NULL)\n\t\tpList->pLastElement = pNewElement;\n\n\tpList->nCount++;\n\tCWSignalElementSafeList(safeList);\n\treturn CW_TRUE;\n}\n\n// No thread-safe\nvoid *CWGetHeadElementFromSafeList(CWSafeList safeList, int *pSize)\n{\n\tCWPrivateSafeElement *pElement;\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\n\tif ((pList == NULL) || (pList->pFirstElement == NULL))\n\t\treturn NULL;\n\n\tpElement = pList->pFirstElement;\n\n\tif (pSize != NULL)\n\t\t*pSize = pElement->nSize;\n\n\treturn pElement->pData;\n}\n\n// No thread-safe\nvoid *CWRemoveHeadElementFromSafeList(CWSafeList safeList, int *pSize)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\tCWPrivateSafeElement *pElement;\n\tvoid *pData;\n\n\tif ((pList == NULL) || (pList->pFirstElement == NULL))\n\t\treturn NULL;\n\n\tpElement = pList->pFirstElement;\n\tpList->pFirstElement = pList->pFirstElement->pNext;\n\tif (pList->pFirstElement == NULL)\n\t\tpList->pLastElement = NULL;\n\telse\n\t\tpList->pFirstElement->pPrev = NULL;\n\n\tpData = pElement->pData;\n\tif (pSize != NULL)\n\t\t*pSize = pElement->nSize;\n\n\tCW_FREE_OBJECT(pElement);\n\n\tpList->nCount--;\n\treturn pData;\n}\n\n// No thread-safe\nvoid *CWRemoveHeadElementFromSafeListwithDataFlag(CWSafeList safeList, int *pSize, CWBool * dataFlag)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\tCWPrivateSafeElement *pElement;\n\tvoid *pData;\n\n\tif ((pList == NULL) || (pList->pFirstElement == NULL))\n\t\treturn NULL;\n\n\tpElement = pList->pFirstElement;\n\tpList->pFirstElement = pList->pFirstElement->pNext;\n\tif (pList->pFirstElement == NULL)\n\t\tpList->pLastElement = NULL;\n\telse\n\t\tpList->pFirstElement->pPrev = NULL;\n\n\tpData = pElement->pData;\n\t*dataFlag = pElement->dataFlag;\n\n\tif (pSize != NULL)\n\t\t*pSize = pElement->nSize;\n\n\tCW_FREE_OBJECT(pElement);\n\n\tpList->nCount--;\n\treturn pData;\n}\n\n// No thread-safe\nCWBool CWAddElementToSafeListTail(CWSafeList safeList, void *pData, int nSize)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\tCWPrivateSafeElement *pNewElement;\n\n\tif ((pList == NULL) || (pData == NULL))\n\t\treturn CW_FALSE;\n\n\tCW_CREATE_OBJECT_ERR(pNewElement, CWPrivateSafeElement, return CW_FALSE;\n\t    );\n\tpNewElement->pData = pData;\n\tpNewElement->nSize = nSize;\n\tpNewElement->pNext = NULL;\n\tpNewElement->pPrev = pList->pLastElement;\n\tif (pList->pLastElement != NULL)\n\t\tpList->pLastElement->pNext = pNewElement;\n\n\tpList->pLastElement = pNewElement;\n\tif (pList->pFirstElement == NULL)\n\t\tpList->pFirstElement = pNewElement;\n\n\tpList->nCount++;\n\tCWSignalElementSafeList(safeList);\n\treturn CW_TRUE;\n}\n\nCWBool CWAddElementToSafeListTailwitDataFlag(CWSafeList safeList, void *pData, int nSize, CWBool dataFlag)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\tCWPrivateSafeElement *pNewElement;\n\n\tif ((pList == NULL) || (pData == NULL))\n\t\treturn CW_FALSE;\n\n\tCW_CREATE_OBJECT_ERR(pNewElement, CWPrivateSafeElement, return CW_FALSE;\n\t    );\n\tpNewElement->pData = pData;\n\tpNewElement->nSize = nSize;\n\tpNewElement->dataFlag = dataFlag;\n\tpNewElement->pNext = NULL;\n\tpNewElement->pPrev = pList->pLastElement;\n\tif (pList->pLastElement != NULL)\n\t\tpList->pLastElement->pNext = pNewElement;\n\n\tpList->pLastElement = pNewElement;\n\tif (pList->pFirstElement == NULL)\n\t\tpList->pFirstElement = pNewElement;\n\n\tpList->nCount++;\n\tCWSignalElementSafeList(safeList);\n\treturn CW_TRUE;\n}\n\n// No thread-safe\nvoid *CWRemoveTailElementFromSafeList(CWSafeList safeList, int *pSize)\n{\n\tCWPrivateSafeList *pList = (CWPrivateSafeList *) safeList;\n\tCWPrivateSafeElement *pElement;\n\tvoid *pData;\n\n\tif ((pList == NULL) || (pList->pLastElement == NULL))\n\t\treturn NULL;\n\n\tpElement = pList->pLastElement;\n\tpList->pLastElement = pList->pLastElement->pPrev;\n\tif (pList->pLastElement == NULL)\n\t\tpList->pFirstElement = NULL;\n\telse\n\t\tpList->pLastElement->pNext = NULL;\n\n\tpData = pElement->pData;\n\tif (pSize != NULL)\n\t\t*pSize = pElement->nSize;\n\n\tCW_FREE_OBJECT(pElement);\n\n\tpList->nCount--;\n\treturn pData;\n}\n\n// No thread-safe\nvoid CWCleanSafeList(CWSafeList safeList, void (*deleteFunc) (void *))\n{\n\tvoid *pData;\n\n\tCW_REPEAT_FOREVER {\n\t\tpData = CWRemoveHeadElementFromSafeList(safeList, NULL);\n\t\tif (pData == NULL)\n\t\t\tbreak;\n\n\t\tif (deleteFunc != NULL)\n\t\t\tdeleteFunc(pData);\n\t}\n}\n"
  },
  {
    "path": "CWSafeList.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWSafeList_HEADER__\n#define __CAPWAP_CWSafeList_HEADER__\n\n#include \"CWThread.h\"\n\ntypedef void *CWSafeList;\n\ntypedef struct _CWPrivateSafeElement {\n\tvoid *pData;\n\tint nSize;\n\tCWBool dataFlag;\n\tstruct _CWPrivateSafeElement *pPrev;\n\tstruct _CWPrivateSafeElement *pNext;\n} CWPrivateSafeElement;\n\ntypedef struct _CWPrivateSafeList {\n\tCWThreadMutex *pThreadMutex;\n\tCWThreadCondition *pThreadCond;\n\n\tunsigned long nCount;\n\tCWPrivateSafeElement *pFirstElement;\n\tCWPrivateSafeElement *pLastElement;\n} CWPrivateSafeList;\n\nCWBool CWCreateSafeList(CWSafeList * pSafeList);\nvoid CWDestroySafeList(CWSafeList safeList);\n\nvoid CWSetMutexSafeList(CWSafeList safeList, CWThreadMutex * pThreadMutex);\nvoid CWSetConditionSafeList(CWSafeList safeList, CWThreadCondition * pThreadCond);\n\nCWBool CWLockSafeList(CWSafeList safeList);\nvoid CWUnlockSafeList(CWSafeList safeList);\nCWBool CWWaitElementFromSafeList(CWSafeList safeList);\nCWBool CWSignalElementSafeList(CWSafeList safeList);\n\nunsigned long CWGetCountElementFromSafeList(CWSafeList safeList);\nCWBool CWAddElementToSafeListHead(CWSafeList safeList, void *pData, int nSize);\nvoid *CWGetHeadElementFromSafeList(CWSafeList safeList, int *pSize);\nvoid *CWRemoveHeadElementFromSafeList(CWSafeList safeList, int *pSize);\nvoid *CWRemoveHeadElementFromSafeListwithDataFlag(CWSafeList safeList, int *pSize, CWBool * dataFlag);\nCWBool CWAddElementToSafeListTail(CWSafeList safeList, void *pData, int nSize);\nCWBool CWAddElementToSafeListTailwitDataFlag(CWSafeList safeList, void *pData, int nSize, CWBool dataFlag);\nvoid *CWRemoveTailElementFromSafeList(CWSafeList safeList, int *pSize);\nvoid CWCleanSafeList(CWSafeList safeList, void (*deleteFunc) (void *));\n\n#endif\n"
  },
  {
    "path": "CWSecurity.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n#include \"CWAC.h\"\n#include <openssl/pkcs12.h>\n#include <openssl/x509v3.h>\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define CW_DTLS_CERT_VERIFY_DEPTH   1\n\n#if (OPENSSL_VERSION_NUMBER < 0x000908000)\n#error \"Must use CAPWAP Hacked OpenSSL 0.9.8a or later\"\n#endif\n\nstatic char *gSecurityPassword;\nstatic CWBool useCertificate;\n\nstatic CWThreadMutex *mutexOpensslBuf = NULL;\n\nCWBool CWSecurityVerifyPeerCertificateForCAPWAP(SSL * ssl, CWBool isClient);\nstatic int CWDTLSPasswordCB(char *buf, int num, int rwflag, void *userdata);\nint CWSecurityVerifyCB(int ok, X509_STORE_CTX * ctx);\n\nunsigned int CWSecurityPSKClientCB(SSL * ssl,\n\t\t\t\t   const char *hint,\n\t\t\t\t   char *identity,\n\t\t\t\t   unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len);\n\nunsigned int CWSecurityPSKServerCB(SSL * ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len);\n\nint psk_key2bn(const char *psk_key, unsigned char *psk, unsigned int max_psk_len);\n\nvoid SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,\n       unsigned int (*callback)(SSL *ssl, const char *identity,\n       unsigned char *psk, unsigned int max_psk_len));\nvoid SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,\n        unsigned int (*callback)(SSL *ssl, const char *hint,\n        char *identity, unsigned int max_identity_len,\n        unsigned char *psk, unsigned int max_psk_len));\n\n#define CWSecurityGetErrorStr()             ((const char *) ERR_error_string(ERR_get_error(), NULL))\n#define CWDTLSGetError()                \"Err\"\n\n#define CWSecurityRaiseError(error)         {                       \\\n                                char buf[256];              \\\n                                ERR_error_string(ERR_get_error(), buf); \\\n                                CWErrorRaise(error, buf);       \\\n                                return CW_FALSE;            \\\n                            }\n\n#define CWSecurityRaiseSystemError(error)       {                       \\\n                                char buf[256];              \\\n                                strerror_r(errno, buf, 256);        \\\n                                CWErrorRaise(error, buf);       \\\n                                return CW_FALSE;            \\\n                            }\n\n#define CWSecurityManageSSLError(arg, session, stuff)   {                       \\\n                                char ___buf[256];           \\\n                                int r;                  \\\n                                                    \\\n                                if((r=(arg)) <= 0) {            \\\n                                    {stuff}             \\\n                                    ERR_error_string(/*SSL_get_error((session),r)*/ ERR_get_error(), ___buf);   \\\n                                    CWDebugLog(strerror(errno));CWErrorRaise(CW_ERROR_GENERAL, ___buf);     \\\n                                    return CW_FALSE;        \\\n                                }                   \\\n                            }\n\nstatic void CWSslLockingFunc(int mode, int n, const char *file, int line)\n{\n\n\tif (mode & CRYPTO_LOCK)\n\t\tCWThreadMutexLock(&mutexOpensslBuf[n]);\n\telse\n\t\tCWThreadMutexUnlock(&mutexOpensslBuf[n]);\n\n\treturn;\n}\n\nstatic unsigned long CWSslIdFunction()\n{\n\n\treturn (unsigned long)pthread_self();\n}\n\nvoid CWSslCleanUp()\n{\n\n\tint i;\n\n\tif (mutexOpensslBuf == NULL)\n\t\treturn;\n\n\tfor (i = 0; i < CRYPTO_num_locks(); i++) {\n\n\t\tCWDestroyThreadMutex(&mutexOpensslBuf[i]);\n\t}\n\n\tCW_FREE_OBJECT(mutexOpensslBuf);\n\tmutexOpensslBuf = NULL;\n\n\treturn;\n}\n\nCWBool CWSecurityInitLib()\n{\n\n\tint i;\n\n\tSSL_load_error_strings();\n\tSSL_library_init();\n\n\t/* setup mutexes for openssl internal locking */\n\tCW_CREATE_ARRAY_ERR(mutexOpensslBuf,\n\t\t\t    CRYPTO_num_locks() * sizeof(CWThreadMutex),\n\t\t\t    CWThreadMutex, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, \"Cannot create openssl mutexes\");\n\t    )\n\n\t    CW_ZERO_MEMORY(mutexOpensslBuf, CRYPTO_num_locks() * sizeof(CWThreadMutex));\n\n\tfor (i = 0; i < CRYPTO_num_locks(); i++) {\n\n\t\tCWBool rv;\n\t\trv = CWCreateThreadMutex(&mutexOpensslBuf[i]);\n\t\tif (rv != CW_TRUE) {\n\n\t\t\tCWSslCleanUp();\n\t\t\treturn CWErrorRaise(CW_ERROR_CREATING, \"Cannot create openssl mutexes\");\n\t\t}\n\t}\n\n\tCRYPTO_set_id_callback(CWSslIdFunction);\n\tCRYPTO_set_locking_callback(CWSslLockingFunc);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWSecurityInitSessionClient(CWSocket sock,\n\t\t\t\t   CWNetworkLev4Address * addrPtr,\n\t\t\t\t   CWSafeList packetReceiveList,\n\t\t\t\t   CWSecurityContext ctx, CWSecuritySession * sessionPtr, int *PMTUPtr)\n{\n\tBIO *sbio = NULL;\n\tCWNetworkLev4Address peer;\n\tint peerlen = sizeof(peer);\n\n\tif (ctx == NULL || sessionPtr == NULL || PMTUPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((*sessionPtr = SSL_new(ctx)) == NULL) {\n\t\tCWSecurityRaiseError(CW_ERROR_CREATING);\n\t}\n#ifdef CW_DEBUGGING\n\tCWDebugLog(\"My Certificate\");\n\tPEM_write_X509(stdout, SSL_get_certificate(*sessionPtr));\n#endif\n\n\tif ((sbio = BIO_new_memory(sock, addrPtr, packetReceiveList)) == NULL) {\n\n\t\tSSL_free(*sessionPtr);\n\t\tCWSecurityRaiseError(CW_ERROR_CREATING);\n\t}\n\n\tif (getsockname(sock, (struct sockaddr *)&peer, (void *)&peerlen) < 0) {\n\n\t\tSSL_free(*sessionPtr);\n\t\tCWSecurityRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\n\t/* BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); // TO-DO (pass MTU?) */\n\tBIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);\n\n\t/*\n\t * TO-DO if we don't set a big MTU, the DTLS implementation will\n\t * not be able to use a big certificate\n\t */\n\t/* BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_MTU, 10000, NULL); */\n\tBIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_MTU, 1388, NULL);\n\n\t/*\n\t * Let the verify_callback catch the verify_depth error so that we get\n\t * an appropriate error in the logfile.\n\t */\n\tSSL_set_verify_depth((*sessionPtr), CW_DTLS_CERT_VERIFY_DEPTH + 1);\n\n\tSSL_set_options((*sessionPtr), SSL_OP_NO_QUERY_MTU);\n\tSSL_set_mtu((*sessionPtr), 1388);\n\n\t/* required by DTLS implementation to avoid data loss */\n\tSSL_set_read_ahead((*sessionPtr), 1);\n\tSSL_set_bio((*sessionPtr), sbio, sbio);\n\tSSL_set_connect_state((*sessionPtr));\n\n\tCWDebugLog(\"Before HS\");\n\tCWSecurityManageSSLError(SSL_do_handshake(*sessionPtr), *sessionPtr, SSL_free(*sessionPtr);\n\t    );\n\tCWDebugLog(\"After HS\");\n\n\tif (SSL_get_verify_result(*sessionPtr) == X509_V_OK) {\n\n\t\tCWDebugLog(\"Certificate Verified\");\n\t} else {\n\n\t\tCWDebugLog(\"Certificate Error (%d)\", SSL_get_verify_result(*sessionPtr));\n\t}\n\n\t/* *PMTUPtr = BIO_ctrl(sbio, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); */\n\t*PMTUPtr = BIO_ctrl(sbio, BIO_CTRL_DGRAM_GET_MTU, 0, NULL);\n\n\tCWDebugLog(\"PMTU: %d\", *PMTUPtr);\n\n\tif (useCertificate) {\n\n\t\tif (CWSecurityVerifyPeerCertificateForCAPWAP((*sessionPtr), CW_TRUE)) {\n\n\t\t\tCWDebugLog(\"Certificate Ok for CAPWAP\");\n\t\t} else {\n\t\t\tCWDebugLog(\"Certificate Not Ok for CAPWAP\");\n#ifndef CW_DEBUGGING\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Certificate Not Ok for CAPWAP\");\n#endif\n\t\t}\n\t}\n\treturn CW_TRUE;\n\n}\n\nvoid CWSecurityCloseSession(CWSecuritySession * sPtr)\n{\n\n\tSSL_free(*sPtr);\n}\n\nCWBool CWSecurityReceive(CWSecuritySession session, char *buf, int len, int *readBytesPtr)\n{\n\n\tCWSecurityManageSSLError((*readBytesPtr = SSL_read(session, buf, len)), session,;\n\t    );\n\n\tCWDebugLog(\"Received packet\\n\");\n\t/*\n\t   if(SSL_read(session, buf, len) <= 0) {\n\t   if((SSL_get_shutdown(session) & SSL_RECEIVED_SHUTDOWN) == SSL_RECEIVED_SHUTDOWN) { // session aborted by peer\n\t   CWDebugLog(\"Connection Aborted by Peer\");\n\t   SSL_shutdown(session); // respond\n\t   return CW_ABORTED;\n\t   }\n\n\t   // error...\n\t   }\n\t */\n\treturn CW_TRUE;\n}\n\nCWBool CWSecuritySend(CWSecuritySession session, const char *buf, int len)\n{\n\n\tif (buf == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWSecurityManageSSLError(SSL_write(session, buf, len), session,;\n\t    );\n\tCWDebugLog(\"Packet Sent\\n\");\n\treturn CW_TRUE;\n}\n\nCWBool CWSecurityInitSessionServer(CWWTPManager * pWtp,\n\t\t\t\t   CWSocket sock, CWSecurityContext ctx, CWSecuritySession * sessionPtr, int *PMTUPtr)\n{\n\tBIO *sbio = NULL;\n\n\tif (ctx == NULL || sessionPtr == NULL || PMTUPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((*sessionPtr = SSL_new(ctx)) == NULL) {\n\t\tCWSecurityRaiseError(CW_ERROR_CREATING);\n\t}\n\n\tif ((sbio = BIO_new_memory(sock, &pWtp->address, pWtp->packetReceiveList)) == NULL) {\n\n\t\tSSL_free(*sessionPtr);\n\t\tCWSecurityRaiseError(CW_ERROR_CREATING);\n\t}\n\n\t/* BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); // TO-DO (pass MTU?) */\n\tBIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);\n\n\t/*\n\t * TO-DO if we don't set a big MTU, the DTLS implementation will\n\t * not be able to use a big certificate\n\t */\n\t/* BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_MTU, 10000, NULL); */\n\tBIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_MTU, 1388, NULL);\n\n\t/*\n\t * Let the verify_callback catch the verify_depth error so that we get\n\t * an appropriate error in the logfile.\n\t */\n\tSSL_set_verify_depth((*sessionPtr), CW_DTLS_CERT_VERIFY_DEPTH + 1);\n\n\tSSL_set_options((*sessionPtr), SSL_OP_NO_QUERY_MTU);\n\tSSL_set_mtu((*sessionPtr), 1388);\n\n\t/* required by DTLS implementation to avoid data loss */\n\tSSL_set_read_ahead((*sessionPtr), 1);\n\t/* turn on cookie exchange */\n\tSSL_set_options((*sessionPtr), SSL_OP_COOKIE_EXCHANGE);\n\t/* set the same bio for reading and writing */\n\tSSL_set_bio((*sessionPtr), sbio, sbio);\n\t/* tell OpenSSL we are a server */\n\tSSL_set_accept_state((*sessionPtr));\n\n\tCWDebugLog(\"Before HS\");\n\tCWSecurityManageSSLError(SSL_do_handshake(*sessionPtr), *sessionPtr, SSL_free(*sessionPtr);\n\t    );\n\tCWDebugLog(\"After HS\");\n\n\tif (SSL_get_verify_result(*sessionPtr) == X509_V_OK) {\n\n\t\tCWDebugLog(\"Certificate Verified\");\n\t} else {\n\t\tCWDebugLog(\"Certificate Error (%d)\", SSL_get_verify_result(*sessionPtr));\n\t}\n\n\tif (useCertificate) {\n\n\t\tif (CWSecurityVerifyPeerCertificateForCAPWAP((*sessionPtr), CW_FALSE)) {\n\n\t\t\tCWDebugLog(\"Certificate Ok for CAPWAP\");\n\t\t} else {\n\t\t\tCWDebugLog(\"Certificate Not Ok for CAPWAP\");\n#ifndef CW_DEBUGGING\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Certificate Not Ok for CAPWAP\");\n#endif\n\t\t}\n\t}\n\n\t/* PMTUPtr = BIO_ctrl(sbio, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); */\n\t*PMTUPtr = BIO_ctrl(sbio, BIO_CTRL_DGRAM_GET_MTU, 0, NULL);\n\n\tCWDebugLog(\"PMTU: %d\", *PMTUPtr);\n\n\treturn CW_TRUE;\n}\n\n/*\n *  NULL caList means that we want pre-shared keys\n */\nCWBool CWSecurityInitContext(CWSecurityContext * ctxPtr,\n\t\t\t     const char *caList,\n\t\t\t     const char *keyfile, const char *passw, CWBool isClient, int (*hackPtr) (void *))\n{\n\n\tif (ctxPtr == NULL || (caList != NULL && (keyfile == NULL || passw == NULL))) {\n\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\tif (((*ctxPtr) = SSL_CTX_new((isClient) ? DTLSv1_client_method() : DTLSv1_server_method())) == NULL) {\n\n\t\tCWSecurityRaiseError(CW_ERROR_CREATING);\n\t}\n\n\t/* certificates */\n\tif (caList != NULL) {\n\t\tuseCertificate = CW_TRUE;\n\t\t/* load keys and certificates */\n\t\tif (!(SSL_CTX_use_certificate_file((*ctxPtr), keyfile, SSL_FILETYPE_PEM))) {\n\t\t\tSSL_CTX_free((*ctxPtr));\n\t\t\tCWSecurityRaiseError(CW_ERROR_GENERAL);\n\t\t}\n\n\t\t/* store password */\n\t\tgSecurityPassword = (char *)passw;\n\t\tSSL_CTX_set_default_passwd_cb((*ctxPtr), CWDTLSPasswordCB);\n\n\t\tif (!(SSL_CTX_use_PrivateKey_file((*ctxPtr), keyfile, SSL_FILETYPE_PEM))) {\n\n\t\t\tSSL_CTX_free((*ctxPtr));\n\t\t\tCWSecurityRaiseError(CW_ERROR_GENERAL);\n\t\t}\n\n\t\tif (!SSL_CTX_check_private_key((*ctxPtr))) {\n\n\t\t\tSSL_CTX_free((*ctxPtr));\n\t\t\tCWSecurityRaiseError(CW_ERROR_GENERAL);\n\t\t}\n\n\t\t/* load the CAs we trust */\n\t\tif (!(SSL_CTX_load_verify_locations((*ctxPtr), caList, 0))) {\n\t\t\tSSL_CTX_free((*ctxPtr));\n\t\t\tCWSecurityRaiseError(CW_ERROR_GENERAL);\n\t\t}\n\n\t\tSSL_CTX_set_default_verify_paths((*ctxPtr));\n\n\t\tif (!isClient) {\n\t\t\t/* require client authentication */\n\t\t\tSSL_CTX_set_verify((*ctxPtr),\n\t\t\t\t\t   SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, CWSecurityVerifyCB);\n\t\t} else {\n\t\t\tSSL_CTX_set_verify((*ctxPtr), SSL_VERIFY_PEER, CWSecurityVerifyCB);\n\t\t}\n\n\t\t/* RFC 5415 ciphers:\n\t\t *\n\t\t * MUST support:\n\t\t * - TLS_RSA_WITH_AES_128_CBC_SHA\n\t\t *\n\t\t * SHOULD support:\n\t\t * - TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n\t\t * - TLS_RSA_WITH_AES_256_CBC_SHA\n\t\t *\n\t\t * MAY support:\n\t\t * - TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n\t\t *\n\t\t * Explicitly add ECDHE ciphers as they are much faster, especialy on slower hardware\n\t\t */\n\n\t\t/* set the ciphers supported by CAPWAP */\n\t\tSSL_CTX_set_cipher_list((*ctxPtr), \"ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:AES128-SHA\");\n\t} else {\n\t\t/* pre-shared keys */\n\n\t\t/* RFC 5415 ciphers:\n\t\t *\n\t\t * MUST support:\n\t\t * - TLS_PSK_WITH_AES_128_CBC_SHA\n\t\t * - TLS_DHE_PSK_WITH_AES_128_CBC_SHA (not supported in OpenSSL)\n\t\t *\n\t\t * MAY support:\n\t\t * - TLS_PSK_WITH_AES_256_CBC_SHA\n\t\t * - TLS_DHE_PSK_WITH_AES_256_CBC_SHA (not supported in OpenSSL)\n\t\t */\n\n\t\tuseCertificate = CW_FALSE;\n\t\tSSL_CTX_set_cipher_list((*ctxPtr), \"PSK-AES128-CBC-SHA:PSK-AES256-CBC-SHA\");\n\n\t\tif(isClient) {\n\t\t\tCWDebugLog(\"Client PSK\");\n\t\t\tSSL_CTX_set_psk_client_callback( (*ctxPtr), CWSecurityPSKClientCB);\n\t\t} else {\n\t\t\tCWDebugLog(\"Server PSK\");\n\t\t\tSSL_CTX_set_psk_server_callback( (*ctxPtr), CWSecurityPSKServerCB);\n\t\t}\n\t}\n\n\t/* needed for DTLS */\n\tSSL_CTX_set_read_ahead((*ctxPtr), 1);\n\n\treturn CW_TRUE;\n}\n\nvoid CWSecurityDestroyContext(CWSecurityContext ctx)\n{\n\n\tif (ctx != NULL)\n\t\tSSL_CTX_free(ctx);\n}\n\nvoid CWSecurityDestroySession(CWSecuritySession s)\n{\n\n\tif (s != NULL) {\n\t\t//if(s->rbio != NULL) BIO_free(s->rbio);\n\t\tSSL_free(s);\n\t}\n}\n\nCWBool CWSecurityVerifyCertEKU(X509 * x509, const char *const expected_oid)\n{\n\n\tEXTENDED_KEY_USAGE *eku = NULL;\n\tCWBool fFound = CW_FALSE;\n\n\t/* LE-03-02-2010.02 */\n\tif (x509 == NULL)\n\t\treturn CW_FALSE;\n\n\tif ((eku = (EXTENDED_KEY_USAGE *) X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL)) == NULL) {\n\n\t\tCWDebugLog(\"Certificate does not have extended key usage extension\");\n\t} else {\n\t\tint i;\n\n\t\tCWDebugLog(\"Validating certificate extended key usage\");\n\t\tfor (i = 0; !fFound && i < sk_ASN1_OBJECT_num(eku); i++) {\n\t\t\tASN1_OBJECT *oid = sk_ASN1_OBJECT_value(eku, i);\n\t\t\tchar szOid[1024];\n\n\t\t\tif (!fFound && OBJ_obj2txt(szOid, sizeof(szOid), oid, 0) != -1) {\n\t\t\t\tCWDebugLog(\"Certificate has EKU (str) %s, expects %s\", szOid, expected_oid);\n\t\t\t\tif (!strcmp(expected_oid, szOid)) {\n\t\t\t\t\tfFound = CW_TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!fFound && OBJ_obj2txt(szOid, sizeof(szOid), oid, 1) != -1) {\n\t\t\t\tCWDebugLog(\"Certificate has EKU (oid) %s, expects %s\", szOid, expected_oid);\n\t\t\t\tif (!strcmp(expected_oid, szOid)) {\n\t\t\t\t\tfFound = CW_TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (eku != NULL) {\n\t\tsk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free);\n\t}\n\n\treturn fFound;\n}\n\n/*\n * modificare questa funzione\n */\nCWBool CWSecurityVerifyPeerCertificateForCAPWAP(SSL * ssl, CWBool isClient)\n{\n\tif (ssl == NULL)\n\t\treturn CW_FALSE;\n\n\tif (!isClient) {\n\t\treturn CWSecurityVerifyCertEKU(SSL_get_peer_certificate(ssl), \"1.3.6.1.5.5.7.3.19\");\t/* value expected for WTP */\n\t} else {\n\t\treturn CWSecurityVerifyCertEKU(SSL_get_peer_certificate(ssl), \"1.3.6.1.5.5.7.3.18\");\t/* value expected for AC */\n\t}\n}\n\n/*\n * callbacks\n */\nstatic int CWDTLSPasswordCB(char *buf, int num, int rwflag, void *userdata)\n{\n\n\tif (buf == NULL || num < strlen(gSecurityPassword) + 1)\n\t\treturn 0;\n\n\tstrcpy(buf, gSecurityPassword);\n\n\treturn strlen(gSecurityPassword);\n}\n\nint CWSecurityVerifyCB(int ok, X509_STORE_CTX * ctx)\n{\n\n\tchar buf[256];\n\tX509 *err_cert;\n\tint err, depth;\n\tint preverify_ok = 1;\n\n\terr_cert = X509_STORE_CTX_get_current_cert(ctx);\n\n\terr = X509_STORE_CTX_get_error(ctx);\n\tCWDebugLog(X509_verify_cert_error_string(err));\n\n\tdepth = X509_STORE_CTX_get_error_depth(ctx);\n\n\t/*\n\t * Retrieve the pointer to the SSL of the connection currently treated\n\t * and the application specific data stored into the SSL object.\n\t */\n\tX509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);\n\n\t/*\n\t * Catch a too long certificate chain. The depth limit set using\n\t * SSL_CTX_set_verify_depth() is by purpose set to \"limit+1\" so\n\t * That whenever the \"depth>verify_depth\" condition is met, we\n\t * have violated the limit and want to log this error condition.\n\t * We must do it here, because the CHAIN_TOO_LONG error would not\n\t * be found explicitly; only errors introduced by cutting off the\n\t * additional certificates would be logged.\n\t */\n\n\tif (depth > CW_DTLS_CERT_VERIFY_DEPTH) {\n\t\tpreverify_ok = 0;\n\t\terr = X509_V_ERR_CERT_CHAIN_TOO_LONG;\n\t\tX509_STORE_CTX_set_error(ctx, err);\n\t}\n\n\tif (!preverify_ok) {\n\n\t\tCWDebugLog(\"verify error:num=%d:%s:depth=%d:%s\\n\", err, X509_verify_cert_error_string(err), depth, buf);\n\t} else {\n\t\tCWDebugLog(\"depth=%d:%s\\n\", depth, buf);\n\t}\n\n\t/*\n\t * At this point, err contains the last verification error. We can use\n\t * it for something special\n\t */\n\tif (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {\n\n\t\tX509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);\n\t\tCWDebugLog(\"issuer= %s\\n\", buf);\n\t}\n\treturn preverify_ok;\n}\n\nunsigned int CWSecurityPSKClientCB(SSL * ssl,\n\t\t\t\t   const char *hint,\n\t\t\t\t   char *identity,\n\t\t\t\t   unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len)\n{\n\n\t/* TO-DO load identity from config */\n\tif (snprintf(identity, max_identity_len, \"CLient_identity\") < 0)\n\t\treturn 0;\n\n\t/* TO-DO load keys from... Plain-text config file? Leave them hard-coded? */\n\treturn psk_key2bn(\"1a2b3c\", psk, max_psk_len);\n}\n\nunsigned int CWSecurityPSKServerCB(SSL * ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len)\n{\n\n\tCWDebugLog(\"Identity: %s, PSK: %s\", identity, psk);\n\t/* TO-DO load keys from... Plain-text config file? Leave them hard-coded? */\n\treturn psk_key2bn(\"1a2b3c\", psk, max_psk_len);\n}\n\n/*\n * Convert the PSK key (psk_key) in ascii to binary (psk).\n */\nint psk_key2bn(const char *psk_key, unsigned char *psk, unsigned int max_psk_len)\n{\n\n\tunsigned int psk_len = 0;\n\tint ret;\n\tBIGNUM *bn = NULL;\n\n\tret = BN_hex2bn(&bn, psk_key);\n\tif (!ret) {\n\n\t\tprintf(\"Could not convert PSK key '%s' to BIGNUM\\n\", psk_key);\n\t\tif (bn)\n\t\t\tBN_free(bn);\n\t\treturn 0;\n\t}\n\n\tif (BN_num_bytes(bn) > max_psk_len) {\n\n\t\tprintf(\"psk buffer of callback is too small (%d) for key (%d)\\n\", max_psk_len, BN_num_bytes(bn));\n\t\tBN_free(bn);\n\t\treturn 0;\n\t}\n\tpsk_len = BN_bn2bin(bn, psk);\n\tBN_free(bn);\n\n\tif (psk_len < 0)\n\t\tgoto out_err;\n\treturn psk_len;\n out_err:\n\treturn 0;\n}\n"
  },
  {
    "path": "CWSecurity.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWSecurity_HEADER__\n#define __CAPWAP_CWSecurity_HEADER__\n\n#include <openssl/ssl.h>\n#include <openssl/bio.h>\n#include <openssl/err.h>\n\ntypedef SSL_CTX *CWSecurityContext;\ntypedef SSL *CWSecuritySession;\n\n#define CWSecuritySetPeerForSession(session, addrPtr)   BIO_ctrl((session)->rbio, BIO_CTRL_DGRAM_SET_PEER, 1, (addrPtr))\n\nCWBool CWSecurityInitLib(void);\nCWBool CWSecurityInitSessionClient(CWSocket sock,\n\t\t\t\t   CWNetworkLev4Address * addrPtr,\n\t\t\t\t   CWSafeList packetReceiveList,\n\t\t\t\t   CWSecurityContext ctx, CWSecuritySession * sessionPtr, int *PMTUPtr);\n\nCWBool CWSecuritySend(CWSecuritySession session, const char *buf, int len);\nCWBool CWSecurityReceive(CWSecuritySession session, char *buf, int len, int *readBytesPtr);\n\nCWBool CWSecurityInitContext(CWSecurityContext * ctxPtr,\n\t\t\t     const char *caList,\n\t\t\t     const char *keyfile, const char *passw, CWBool isClient, int (*hackPtr) (void *));\n\nvoid CWSecurityDestroyContext(CWSecurityContext ctx);\nvoid CWSecurityDestroySession(CWSecuritySession s);\n\nBIO *BIO_new_memory(CWSocket sock, CWNetworkLev4Address * pSendAddress, CWSafeList * pRecvAddress);\n\nvoid CWSslCleanUp();\n\n#endif\n"
  },
  {
    "path": "CWStevens.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include    \"CWCommon.h\"\n#include <sys/un.h>\n#ifdef  HAVE_SOCKADDR_DL_STRUCT\n#include    <net/if_dl.h>\n#endif\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n// an extension to Unix Network Programming's library: a thread-safe version of sock_ntop and a couple of\n// functions to manage port number in IPv4/6\n\n/* include sock_ntop */\nchar *sock_ntop_r(const struct sockaddr *sa, char *str)\n{\n\tchar portstr[8];\n\n\tswitch (sa->sa_family) {\n\tcase AF_INET:{\n\t\t\tstruct sockaddr_in *sin = (struct sockaddr_in *)sa;\n\n\t\t\tif (inet_ntop(AF_INET, &sin->sin_addr, str, 128) == 0)\n\t\t\t\treturn (NULL);\n\t\t\tif (ntohs(sin->sin_port) != 0) {\n\t\t\t\tsnprintf(portstr, sizeof(portstr), \":%d\", ntohs(sin->sin_port));\n\t\t\t\tstrcat(str, portstr);\n\t\t\t}\n\t\t\treturn (str);\n\t\t}\n\t\t/* end sock_ntop */\n\n#ifdef  IPV6\n\tcase AF_INET6:{\n\t\t\tstruct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;\n\n\t\t\tstr[0] = '[';\n\t\t\tif (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, 128 - 1) == NULL)\n\t\t\t\treturn (NULL);\n\t\t\tif (ntohs(sin6->sin6_port) != 0) {\n\t\t\t\tsnprintf(portstr, sizeof(portstr), \"]:%d\", ntohs(sin6->sin6_port));\n\t\t\t\tstrcat(str, portstr);\n\t\t\t\treturn (str);\n\t\t\t}\n\t\t\treturn (str + 1);\n\t\t}\n#endif\n\n#ifdef  AF_UNIX\n\tcase AF_UNIX:{\n\t\t\tstruct sockaddr_un *unp = (struct sockaddr_un *)sa;\n\n\t\t\t/* OK to have no pathname bound to the socket: happens on\n\t\t\t   every connect() unless client calls bind() first. */\n\t\t\tif (unp->sun_path[0] == 0)\n\t\t\t\tstrcpy(str, \"(no pathname bound)\");\n\t\t\telse\n\t\t\t\tsnprintf(str, 128, \"%s\", unp->sun_path);\n\t\t\treturn (str);\n\t\t}\n#endif\n\n#ifdef  HAVE_SOCKADDR_DL_STRUCT\n\tcase AF_LINK:{\n\t\t\tstruct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;\n\n\t\t\tif (sdl->sdl_nlen > 0)\n\t\t\t\tsnprintf(str, 128, \"%*s (index %d)\", sdl->sdl_nlen, &sdl->sdl_data[0], sdl->sdl_index);\n\t\t\telse\n\t\t\t\tsnprintf(str, 128, \"AF_LINK, index=%d\", sdl->sdl_index);\n\t\t\treturn (str);\n\t\t}\n#endif\n\tdefault:\n\t\tsnprintf(str, 128, \"sock_ntop: unknown AF_xxx: %d\", sa->sa_family);\n\t\treturn (str);\n\t}\n\treturn (NULL);\n}\n\nint sock_cpy_addr_port(struct sockaddr *sa1, const struct sockaddr *sa2)\n{\n\tsa1->sa_family = sa2->sa_family;\n\n\tswitch (sa1->sa_family) {\n\tcase AF_INET:{\n\t\t\t(memcpy(&((struct sockaddr_in *)sa1)->sin_addr,\n\t\t\t\t&((struct sockaddr_in *)sa2)->sin_addr, sizeof(struct in_addr)));\n\t\t\t((struct sockaddr_in *)sa1)->sin_port = ((struct sockaddr_in *)sa2)->sin_port;\n\t\t\treturn 0;\n\t\t}\n\n#ifdef  IPV6\n\tcase AF_INET6:{\n\t\t\t(memcpy(&((struct sockaddr_in6 *)sa1)->sin6_addr,\n\t\t\t\t&((struct sockaddr_in6 *)sa2)->sin6_addr, sizeof(struct in6_addr)));\n\n\t\t\t(((struct sockaddr_in6 *)sa1)->sin6_port = ((struct sockaddr_in6 *)sa2)->sin6_port);\n\t\t\treturn 0;\n\t\t}\n#endif\n\n#ifdef  AF_UNIX\n\tcase AF_UNIX:{\n\t\t\t(strcpy(((struct sockaddr_un *)sa1)->sun_path, ((struct sockaddr_un *)sa2)->sun_path));\n\t\t\treturn 0;\n\t\t}\n#endif\n\n#ifdef  HAVE_SOCKADDR_DL_STRUCT\n\tcase AF_LINK:{\n\t\t\treturn (-1);\t/* no idea what to copy here ? */\n\t\t}\n#endif\n\t}\n\treturn (-1);\n}\n\nvoid sock_set_port_cw(struct sockaddr *sa, int port)\n{\n\tswitch (sa->sa_family) {\n\tcase AF_INET:{\n\t\t\tstruct sockaddr_in *sin = (struct sockaddr_in *)sa;\n\n\t\t\tsin->sin_port = port;\n\t\t\treturn;\n\t\t}\n\n#ifdef  IPV6\n\tcase AF_INET6:{\n\t\t\tstruct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;\n\n\t\t\tsin6->sin6_port = port;\n\t\t\treturn;\n\t\t}\n#endif\n\t}\n\n\treturn;\n}\n\nstruct ifi_info *get_ifi_info(int family, int doaliases)\n{\n\tstruct ifi_info *ifi, *ifihead, **ifipnext;\n\tint sockfd, len, lastlen, flags, idx = 0;\n\tchar *ptr, *buf, lastname[IFNAMSIZ], *cptr, *sdlname;\n\tstruct ifconf ifc;\n\tstruct ifreq *ifr, ifrcopy;\n\tstruct sockaddr_in *sinptr;\n\tstruct sockaddr_in6 *sin6ptr;\n\n\tsockfd = socket(AF_INET, SOCK_DGRAM, 0);\n\n\tlastlen = 0;\n\tlen = 100 * sizeof(struct ifreq);\t/* initial buffer size guess */\n\tfor (;;) {\n\t\tbuf = (char *)malloc(len);\n\t\tifc.ifc_len = len;\n\t\tifc.ifc_buf = buf;\n\t\tif (ioctl(sockfd, SIOCGIFCONF, &ifc) >= 0) {\n\t\t\tif (ifc.ifc_len == lastlen)\n\t\t\t\tbreak;\t/* success, len has not changed */\n\t\t\tlastlen = ifc.ifc_len;\n\t\t}\n\t\tlen += 10 * sizeof(struct ifreq);\t/* increment */\n\t\tfree(buf);\n\t}\n\tifihead = NULL;\n\tifipnext = &ifihead;\n\tlastname[0] = 0;\n\tsdlname = NULL;\n\n\tfor (ptr = buf; ptr < buf + ifc.ifc_len;) {\n\t\tifr = (struct ifreq *)ptr;\n\n#ifdef  HAVE_SOCKADDR_SA_LEN\n\t\tlen = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);\n#else\n\t\tswitch (ifr->ifr_addr.sa_family) {\n#ifdef  IPV6\n\t\tcase AF_INET6:\n\t\t\tlen = sizeof(struct sockaddr_in6);\n\t\t\tbreak;\n#endif\n\t\tcase AF_INET:\n\t\tdefault:\n\t\t\tlen = sizeof(struct sockaddr);\n\t\t\tbreak;\n\t\t}\n#endif\t\t\t\t/* HAVE_SOCKADDR_SA_LEN */\n\t\tptr += sizeof(struct ifreq);    /* for next one in buffer */\n\n#ifdef  HAVE_SOCKADDR_DL_STRUCT\n\t\t/* assumes that AF_LINK precedes AF_INET or AF_INET6 */\n\t\tif (ifr->ifr_addr.sa_family == AF_LINK) {\n\t\t\tstruct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;\n\t\t\tsdlname = ifr->ifr_name;\n\t\t\tidx = sdl->sdl_index;\n\t\t\thaddr = sdl->sdl_data + sdl->sdl_nlen;\n\t\t\thlen = sdl->sdl_alen;\n\t\t}\n#endif\n\n\t\tif (ifr->ifr_addr.sa_family != family)\n\t\t\tcontinue;\t/* ignore if not desired address family */\n\n\t\tif ((cptr = strchr(ifr->ifr_name, ':')) != NULL)\n\t\t\t*cptr = 0;\t/* replace colon with null */\n\t\tif (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {\n\t\t\tif (doaliases == 0)\n\t\t\t\tcontinue;\t/* already processed this interface */\n\t\t}\n\t\tmemcpy(lastname, ifr->ifr_name, IFNAMSIZ);\n\n\t\tifrcopy = *ifr;\n\t\tioctl(sockfd, SIOCGIFFLAGS, &ifrcopy);\n\t\tflags = ifrcopy.ifr_flags;\n\t\tif ((flags & IFF_UP) == 0)\n\t\t\tcontinue;\t/* ignore if interface not up */\n\n\t\tifi = (struct ifi_info *)calloc(1, sizeof(struct ifi_info));\n\t\t*ifipnext = ifi;\t/* prev points to this new one */\n\t\tifipnext = &ifi->ifi_next;\t/* pointer to next one goes here */\n\n\t\tifi->ifi_flags = flags;\t/* IFF_xxx values */\n\t\tmemcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);\n\t\tifi->ifi_name[IFI_NAME - 1] = '\\0';\n\t\t/* If the sockaddr_dl is from a different interface, ignore it */\n\t\tif (sdlname == NULL || strcmp(sdlname, ifr->ifr_name) != 0)\n\t\t\tidx = 0;\n\t\tifi->ifi_index = idx;\n\n\t\tswitch (ifr->ifr_addr.sa_family) {\n\t\tcase AF_INET:\n\t\t\tsinptr = (struct sockaddr_in *)&ifr->ifr_addr;\n\t\t\tifi->ifi_addr = (struct sockaddr *)calloc(1, sizeof(struct sockaddr_in));\n\t\t\tmemcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));\n\n#ifdef  SIOCGIFBRDADDR\n\t\t\tif (flags & IFF_BROADCAST) {\n\t\t\t\tioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy);\n\t\t\t\tsinptr = (struct sockaddr_in *)&ifrcopy.ifr_broadaddr;\n\t\t\t\tifi->ifi_brdaddr = (struct sockaddr *)calloc(1, sizeof(struct sockaddr_in));\n\t\t\t\tmemcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));\n\t\t\t}\n#endif\n\t\t\t/*\n\t\t\t * LE03 - Donato Capitella\n\t\t\t */\n\t\t\tbreak;\n\t\tcase AF_INET6:\n\t\t\tsin6ptr = (struct sockaddr_in6 *)&ifr->ifr_addr;\n\t\t\tifi->ifi_addr = (struct sockaddr *)calloc(1, sizeof(struct sockaddr_in6));\n\t\t\tmemcpy(ifi->ifi_addr, sin6ptr, sizeof(struct sockaddr_in6));\n\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\tfree(buf);\n\treturn (ifihead);\t/* pointer to first structure in linked list */\n}\n\n/* end get_ifi_info4 */\n\n/* include free_ifi_info */\nvoid free_ifi_info(struct ifi_info *ifihead)\n{\n\tstruct ifi_info *ifi, *ifinext;\n\n\tfor (ifi = ifihead; ifi != NULL; ifi = ifinext) {\n\t\tif (ifi->ifi_addr != NULL)\n\t\t\tfree(ifi->ifi_addr);\n\t\tif (ifi->ifi_brdaddr != NULL)\n\t\t\tfree(ifi->ifi_brdaddr);\n\t\tifinext = ifi->ifi_next;\t/* can't fetch ifi_next after free() */\n\t\tfree(ifi);\t/* the ifi_info{} itself */\n\t}\n}\n\n/* end free_ifi_info */\n\nint sock_cmp_port(const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen)\n{\n\tif (sa1->sa_family != sa2->sa_family)\n\t\treturn (-1);\n\n\tswitch (sa1->sa_family) {\n\tcase AF_INET:{\n\t\t\treturn (memcmp(&((struct sockaddr_in *)sa1)->sin_port,\n\t\t\t\t       &((struct sockaddr_in *)sa2)->sin_port,\n\t\t\t\t       sizeof(((struct sockaddr_in *) sa1)->sin_port)));\n\t\t}\n\n#ifdef  IPV6\n\tcase AF_INET6:{\n\t\t\treturn (memcmp(&((struct sockaddr_in6 *)sa1)->sin6_port,\n\t\t\t\t       &((struct sockaddr_in6 *)sa2)->sin6_port,\n\t\t\t\t       sizeof(((struct sockaddr_in6 *) sa1)->sin6_port)));\n\t\t}\n#endif\n\n#ifdef  AF_UNIX\n\tcase AF_UNIX:{\n\t\t\treturn (-1);\n\t\t}\n#endif\n\n#ifdef  HAVE_SOCKADDR_DL_STRUCT\n\tcase AF_LINK:{\n\t\t\treturn (-1);\t/* no idea what to compare here ? */\n\t\t}\n#endif\n\t}\n\treturn (-1);\n}\n\nint sock_cmp_addr(const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen)\n{\n\tif (sa1->sa_family != sa2->sa_family)\n\t\treturn (-1);\n\n\tswitch (sa1->sa_family) {\n\tcase AF_INET:{\n\t\t\treturn (memcmp(&((struct sockaddr_in *)sa1)->sin_addr,\n\t\t\t\t       &((struct sockaddr_in *)sa2)->sin_addr, sizeof(struct in_addr)));\n\t\t}\n\n#ifdef  IPV6\n\tcase AF_INET6:{\n\t\t\treturn (memcmp(&((struct sockaddr_in6 *)sa1)->sin6_addr,\n\t\t\t\t       &((struct sockaddr_in6 *)sa2)->sin6_addr, sizeof(struct in6_addr)));\n\t\t}\n#endif\n\n#ifdef  AF_UNIX\n\tcase AF_UNIX:{\n\t\t\treturn (strcmp(((struct sockaddr_un *)sa1)->sun_path, ((struct sockaddr_un *)sa2)->sun_path));\n\t\t}\n#endif\n\n#ifdef  HAVE_SOCKADDR_DL_STRUCT\n\tcase AF_LINK:{\n\t\t\treturn (-1);\t/* no idea what to compare here ? */\n\t\t}\n#endif\n\t}\n\treturn (-1);\n}\n\nint mcast_join(int sockfd, const struct sockaddr *grp, socklen_t grplen, const char *ifname, u_int ifindex)\n{\n\t/* include mcast_join2 */\n\tswitch (grp->sa_family) {\n\tcase AF_INET:{\n\t\t\tstruct ip_mreq mreq;\n\t\t\tstruct ifreq ifreq;\n\n\t\t\tmemcpy(&mreq.imr_multiaddr,\n\t\t\t       &((const struct sockaddr_in *)grp)->sin_addr, sizeof(struct in_addr));\n\n\t\t\tif (ifindex > 0) {\n\t\t\t\tif (if_indextoname(ifindex, ifreq.ifr_name) == NULL) {\n\t\t\t\t\terrno = ENXIO;\t/* i/f index not found */\n\t\t\t\t\treturn (-1);\n\t\t\t\t}\n\t\t\t\tgoto doioctl;\n\t\t\t} else if (ifname != NULL) {\n\t\t\t\tstrncpy(ifreq.ifr_name, ifname, IFNAMSIZ);\n doioctl:\n\t\t\t\tif (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0)\n\t\t\t\t\treturn (-1);\n\t\t\t\tmemcpy(&mreq.imr_interface,\n\t\t\t\t       &((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr));\n\t\t\t} else\n\t\t\t\tmreq.imr_interface.s_addr = htonl(INADDR_ANY);\n\n\t\t\treturn (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)));\n\t\t}\n\t\t/* end mcast_join2 */\n\n\t\t/* include mcast_join3 */\n#ifdef  IPV6\n#ifndef IPV6_JOIN_GROUP\t\t/* APIv0 compatibility */\n#define IPV6_JOIN_GROUP     IPV6_ADD_MEMBERSHIP\n#endif\n\tcase AF_INET6:{\n\t\t\tstruct ipv6_mreq mreq6;\n\n\t\t\tmemcpy(&mreq6.ipv6mr_multiaddr,\n\t\t\t       &((const struct sockaddr_in6 *)grp)->sin6_addr, sizeof(struct in6_addr));\n\n\t\t\tif (ifindex > 0) {\n\t\t\t\tmreq6.ipv6mr_interface = ifindex;\n\t\t\t} else if (ifname != NULL) {\n\t\t\t\tif ((mreq6.ipv6mr_interface = if_nametoindex(ifname)) == 0) {\n\t\t\t\t\terrno = ENXIO;\t/* i/f name not found */\n\t\t\t\t\treturn (-1);\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\tmreq6.ipv6mr_interface = 0;\n\n\t\t\treturn (setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)));\n\t\t}\n#endif\n\n\tdefault:\n\t\terrno = EAFNOSUPPORT;\n\t\treturn (-1);\n\t}\n}\n\n/* end mcast_join3 */\n\nint /* Write \"n\" bytes to a descriptor. */ writen(int fd, const void *vptr, size_t n)\n{\n\tsize_t nleft;\n\tssize_t nwritten;\n\tconst char *ptr;\n\n\tptr = vptr;\n\tnleft = n;\n\twhile (nleft > 0) {\n\t\tif ((nwritten = send(fd, ptr, nleft, 0)) <= 0) {\n\t\t\tif (errno == EINTR)\n\t\t\t\tnwritten = 0;\t/* and call write() again */\n\t\t\telse\n\t\t\t\treturn (-1);\t/* error */\n\t\t}\n\n\t\tnleft -= nwritten;\n\t\tptr += nwritten;\n\t}\n\treturn (n);\n}\n\nint Writen(int fd, void *ptr, size_t nbytes)\n{\n\tif (writen(fd, ptr, nbytes) != nbytes)\n\t\treturn -1;\n\treturn nbytes;\n}\n"
  },
  {
    "path": "CWStevens.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWStevens_HEADER__\n#define __CAPWAP_CWStevens_HEADER__\n\n#include <net/if.h>\n#include <sys/ioctl.h>\n\n#define IFI_NAME    16\t\t/* same as IFNAMSIZ in <net/if.h> */\n#define IFI_HADDR    8\t\t/* allow for 64-bit EUI-64 in future */\n\nstruct ifi_info {\n\tchar ifi_name[IFI_NAME];\t/* interface name, null-terminated */\n\tshort ifi_index;\t/* interface index */\n\tshort ifi_flags;\t/* IFF_xxx constants from <net/if.h> */\n\tstruct sockaddr *ifi_addr;\t/* primary address */\n\tstruct sockaddr *ifi_brdaddr;\t/* broadcast address */\n\tstruct ifi_info *ifi_next;\t/* next of these structures */\n};\n\nstruct ifi_info *get_ifi_info(int, int);\nvoid free_ifi_info(struct ifi_info *);\nchar *sock_ntop_r(const struct sockaddr *sa, char *str);\nint sock_cpy_addr_port(struct sockaddr *sa1, const struct sockaddr *sa2);\nvoid sock_set_port_cw(struct sockaddr *sa, int port);\nint sock_cmp_port(const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen);\nint sock_cmp_addr(const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen);\nint mcast_join(int sockfd, const struct sockaddr *grp, socklen_t grplen, const char *ifname, u_int ifindex);\nint Writen(int fd, void *ptr, size_t nbytes);\n\n#endif\t\t\t\t/* __CAPWAP_CWStevens_HEADER__ */\n"
  },
  {
    "path": "CWThread.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#include <stdio.h>\n#include <time.h>\n#include <signal.h>\n#include <stdlib.h>\n#include <unistd.h>\n\n#define CW_USE_THREAD_TIMERS\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCW_THREAD_RETURN_TYPE CWThreadManageTimers(void *arg);\n\n// Creates a thread that will execute a given function with a given parameter\nCWBool CWCreateThread(CWThread * newThread, CW_THREAD_FUNCTION threadFunc, void *arg)\n{\n\tif (newThread == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Create Thread\\n\");\n\n\tif (pthread_create(newThread, NULL, threadFunc, arg) != 0) {\n\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE,\n\t\t\t\t    \"Can't create thread (maybe there are too many other threads)\");\n\t}\n\n\treturn CW_TRUE;\n}\n\n// Creates a thread condition (wrapper for pthread_cond_init)\nCWBool CWCreateThreadCondition(CWThreadCondition * theCondition)\n{\n\tif (theCondition == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tswitch (pthread_cond_init(theCondition, NULL)) {\n\tcase 0:\t\t// success\n\t\tbreak;\n\tcase ENOMEM:\n\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\tdefault:\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, \"Can't create thread condition\");\n\t}\n\treturn CW_TRUE;\n}\n\n// Frees a thread condition (wrapper for pthread_cond_destroy)\nvoid CWDestroyThreadCondition(CWThreadCondition * theCondition)\n{\n\tif (theCondition == NULL)\n\t\treturn;\n\tpthread_cond_destroy(theCondition);\n}\n\n// Wait for a thread condition (wrapper for pthread_cond_wait)\nCWBool CWWaitThreadCondition(CWThreadCondition * theCondition, CWThreadMutex * theMutex)\n{\n\n\tif (theCondition == NULL || theMutex == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tswitch (pthread_cond_wait(theCondition, theMutex)) {\n\tcase 0:\t\t// success\n\t\tbreak;\n\tcase ETIMEDOUT:\n\t\treturn CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);\n\tdefault:\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, \"Error waiting on thread condition\");\n\t}\n\n\treturn CW_TRUE;\n}\n\n// Wait for a thread condition (wrapper for pthread_cond_wait)\nCWBool CWWaitThreadConditionTimeout(CWThreadCondition * theCondition, CWThreadMutex * theMutex,\n\t\t\t\t    struct timespec * pTimeout)\n{\n\tif (theCondition == NULL || theMutex == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tswitch (pthread_cond_timedwait(theCondition, theMutex, pTimeout)) {\n\tcase 0:\t\t// success\n\t\tbreak;\n\n\tcase ETIMEDOUT:\n\t\treturn CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);\n\n\tdefault:\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, \"Error waiting on thread condition\");\n\t}\n\n\treturn CW_TRUE;\n}\n\n// Signal a thread condition (wrapper for pthread_cond_signal)\nvoid CWSignalThreadCondition(CWThreadCondition * theCondition)\n{\n\tif (theCondition == NULL)\n\t\treturn;\n\n\tpthread_cond_signal(theCondition);\n}\n\n// Creates a thread mutex (wrapper for pthread_mutex_init)\nCWBool CWCreateThreadMutex(CWThreadMutex * theMutex)\n{\n\tif (theMutex == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tswitch (pthread_mutex_init(theMutex, NULL)) {\n\tcase 0:\t\t// success\n\t\tbreak;\n\tcase ENOMEM:\n\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\tdefault:\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, \"Can't create thread mutex\");\n\t}\n\treturn CW_TRUE;\n}\n\n// Free a thread mutex (wrapper for pthread_mutex_destroy)\nvoid CWDestroyThreadMutex(CWThreadMutex * theMutex)\n{\n\tif (theMutex == NULL)\n\t\treturn;\n\tpthread_mutex_destroy(theMutex);\n}\n\n// locks a mutex among threads at the specified address (blocking)\nCWBool CWThreadMutexLock(CWThreadMutex * theMutex)\n{\n\tif (theMutex == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif (pthread_mutex_lock(theMutex) != 0) {\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, \"Can't lock thread mutex\");\n\t}\n\t/*\n\t   fprintf(stdout, \"Mutex %p locked by %p.\\n\", theMutex, pthread_self());\n\t   fflush(stdout);\n\t */\n\treturn CW_TRUE;\n}\n\n// locks a mutex among threads at the specified address (non-blocking).\n// CW_TRUE if lock was acquired, CW_FALSE otherwise\nCWBool CWThreadMutexTryLock(CWThreadMutex * theMutex)\n{\n\tif (theMutex == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\tif (pthread_mutex_trylock(theMutex) == EBUSY)\n\t\treturn CW_FALSE;\n\telse\n\t\treturn CW_TRUE;\n}\n\n// unlocks a mutex among threads at the specified address\nvoid CWThreadMutexUnlock(CWThreadMutex * theMutex)\n{\n\tif (theMutex == NULL)\n\t\treturn;\n\tpthread_mutex_unlock(theMutex);\n\t/*\n\t   fprintf(stdout, \"Mutex %p UNlocked by %p.\\n\", theMutex, pthread_self());\n\t   fflush(stdout);\n\t */\n}\n\n// creates a semaphore\nCWBool CWThreadCreateSem(CWThreadSem * semPtr, int value)\n{\n\tif (semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// we use named semaphore on platforms that support only them (e.g. Mac OS X)\n#ifdef CW_USE_NAMED_SEMAPHORES\n\t{\n\t\tstatic int semCount = 0;\n\t\tchar name[32];\n\n\t\tsnprintf(name, 32, \"/CWSem-%d-%4.4d\", getpid(), semCount++);\n\t\tif ((semPtr->semPtr = sem_open(name, O_CREAT, 0600, value)) == (sem_t *) SEM_FAILED) {\n\t\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t\t} else {\n\t\t\tsem_unlink(name);\n\t\t}\n\t}\n#else\n\tif (sem_init(semPtr, 0, value) < 0) {\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n#endif\n\n\treturn CW_TRUE;\n}\n\n// destroy a semaphore\nvoid CWThreadDestroySem(CWThreadSem * semPtr)\n{\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tif (semPtr == NULL || semPtr->semPtr == NULL)\n\t\treturn;\n#else\n\tif (semPtr == NULL)\n\t\treturn;\n#endif\n\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tsem_close(semPtr->semPtr);\n#else\n\tsem_destroy(semPtr);\n#endif\n}\n\n// perform wait on a semaphore\nCWBool CWThreadSemWait(CWThreadSem * semPtr)\n{\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tif (semPtr == NULL || semPtr->semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#else\n\tif (semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#endif\n\n\t//CWDebugLog(\"Sem Wait\");\n\n#ifdef CW_USE_NAMED_SEMAPHORES\n\twhile (sem_wait(semPtr->semPtr) < 0) {\n#else\n\twhile (sem_wait(semPtr) < 0) {\n#endif\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\telse {\n\t\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n\n// perform post on a semaphore\nCWBool CWThreadSemPost(CWThreadSem * semPtr)\n{\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tif (semPtr == NULL || semPtr->semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#else\n\tif (semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#endif\n\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tif (sem_post(semPtr->semPtr) < 0) {\n#else\n\tif (sem_post(semPtr) < 0) {\n#endif\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\treturn CW_TRUE;\n}\n\n// get the value of a semaphore\nCWBool CWThreadSemGetValue(CWThreadSem * semPtr, int *valuePtr)\n{\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tif (valuePtr == NULL || semPtr == NULL || semPtr->semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#else\n\tif (valuePtr == NULL || semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#endif\n\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tif (sem_getvalue(semPtr->semPtr, valuePtr) < 0) {\t// note: broken on Mac OS X? Btw we don't need it\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n#else\n\tif (sem_getvalue(semPtr, valuePtr) < 0) {\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n#endif\n\tif (*valuePtr < 0) {\n\t\t*valuePtr = 0;\n\t}\n\n\treturn CW_TRUE;\n}\n\nsem_t *CWThreadGetSemT(CWThreadSem * semPtr)\n{\n#ifdef CW_USE_NAMED_SEMAPHORES\n\treturn (semPtr->semPtr);\n#else\n\treturn semPtr;\n#endif\n}\n\n// creates a semaphore that can be used with CWThreadTimedSemWait(). This type of semaphore\n// is different from CWThreadSemaphore to support platforms that don't have sem_timedwait() (e.g. Mac OS X)\nCWBool CWThreadCreateTimedSem(CWThreadTimedSem * semPtr, int value)\n{\n#ifdef HAVE_SEM_TIMEDWAIT\n\treturn CWThreadCreateSem(semPtr, value);\n#else\n\t// if we don't have sem_timedwait(), the timed semaphore is a pair of unix domain sockets.\n\t// We write a dummy packet on a socket (client) when we want to post, and select() with timer on the other socket\n\t// when we want to wait.\n\tstruct sockaddr_un serverAddr, clientAddr;\n\tint i;\n\n\tif (semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((((*semPtr)[0] = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) || (((*semPtr)[1] = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) {\t// create a pair of datagram unix domain socket\n\t\tclose((*semPtr)[0]);\n\t\tCWErrorRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tCW_ZERO_MEMORY(&serverAddr, sizeof(serverAddr));\n\tserverAddr.sun_family = AF_LOCAL;\n\tif (tmpnam((char *)&(serverAddr.sun_path)) == NULL) {\n\t\tCWErrorRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tCW_ZERO_MEMORY(&clientAddr, sizeof(clientAddr));\n\tclientAddr.sun_family = AF_LOCAL;\n\tif (tmpnam((char *)&(clientAddr.sun_path)) == NULL) {\n\t\tCWErrorRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tif ((bind((*semPtr)[0], (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) || (bind((*semPtr)[1], (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) || (connect((*semPtr)[1], (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) ||\t// connect each socket to the other\n\t    (connect((*semPtr)[0], (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0)\n\t    ) {\n\t\tclose((*semPtr)[0]);\n\t\tclose((*semPtr)[1]);\n\t\tCWErrorRaiseSystemError(CW_ERROR_CREATING);\n\t}\n\n\tfor (i = 0; i < value; i++) {\n\t\tif (!CWThreadTimedSemPost(semPtr))\n\t\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n#endif\n}\n\n// CW_TRUE if the semaphore has zero value, CW_FALSE otherwise\nCWBool CWThreadTimedSemIsZero(CWThreadTimedSem * semPtr)\n{\n#ifdef HAVE_SEM_TIMEDWAIT\n\tint value;\n\tif (!CWThreadSemGetValue(semPtr, &value))\n\t\treturn CW_FALSE;\n\n\treturn (value == 0) ? CW_TRUE : CW_FALSE;\n#else\n\tfd_set fset;\n\tint r;\n\tstruct timeval timeout;\n\n\tif (semPtr == NULL)\n\t\treturn CW_FALSE;\n\n\tFD_ZERO(&fset);\n\tFD_SET((*semPtr)[0], &fset);\n\tFD_SET((*semPtr)[1], &fset);\n\n\ttimeout.tv_sec = 0;\t// poll\n\ttimeout.tv_usec = 0;\n\n\twhile ((r = select(max((*semPtr)[1], (*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) < 0) {\n\t\tif (errno == EINTR) {\n\t\t\ttimeout.tv_sec = 0;\n\t\t\ttimeout.tv_usec = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\treturn (r == 0) ? CW_TRUE : CW_FALSE;\n#endif\n}\n\nCWBool CWThreadTimedSemSetValue(CWThreadTimedSem * semPtr, int value)\n{\n#ifdef HAVE_SEM_TIMEDWAIT\n\t// note: we can implement this, but our implemntation does't really need it in case\n\t// of a system semaphore. This is useful for our Unix Domain Socket Hack\n\treturn CW_TRUE;\n\t//return CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"Operation Not Supported\");\n#else\n\tfd_set fset;\n\tint r, i;\n\tstruct timeval timeout;\n\n\tif (semPtr == NULL)\n\t\treturn CW_FALSE;\n\n\tFD_ZERO(&fset);\n\tFD_SET((*semPtr)[0], &fset);\n\tFD_SET((*semPtr)[1], &fset);\n\n\ttimeout.tv_sec = 0;\t// poll\n\ttimeout.tv_usec = 0;\n\n\t// first, remove all the pending packets\n\tCW_REPEAT_FOREVER {\n\t\tchar dummy;\n\t\twhile ((r = select(max((*semPtr)[1], (*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) < 0) {\n\t\t\tif (errno == EINTR) {\n\t\t\t\ttimeout.tv_sec = 0;\n\t\t\t\ttimeout.tv_usec = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t\t}\n\n\t\tif (r == 0)\n\t\t\tbreak;\n\n\t\tif (FD_ISSET((*semPtr)[0], &fset)) {\n\t\t\twhile (read((*semPtr)[0], &dummy, 1) < 0) {\n\t\t\t\tif (errno == EINTR)\n\t\t\t\t\tcontinue;\n\t\t\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t\t\t}\n\t\t}\n\n\t\tif (FD_ISSET((*semPtr)[1], &fset)) {\n\t\t\twhile (read((*semPtr)[1], &dummy, 1) < 0) {\n\t\t\t\tif (errno == EINTR)\n\t\t\t\t\tcontinue;\n\t\t\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t\t\t}\n\t\t}\n\t}\n\n\t// second, send n packets, where n is the value we want to set for the semaphore\n\tfor (i = 0; i < value; i++) {\n\t\tif (!CWThreadTimedSemPost(semPtr))\n\t\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n#endif\n}\n\nvoid CWThreadDestroyTimedSem(CWThreadTimedSem * semPtr)\n{\n#ifdef HAVE_SEM_TIMEDWAIT\n\tCWThreadDestroySem(semPtr);\n#else\n\tif (semPtr == NULL)\n\t\treturn;\n\tclose((*semPtr)[0]);\n\tclose((*semPtr)[1]);\n#endif\n}\n\nCWBool CWThreadTimedSemWait(CWThreadTimedSem * semPtr, time_t sec, time_t nsec)\n{\n#ifdef HAVE_SEM_TIMEDWAIT\n\tstruct timespec timeout;\n\ttime_t t;\n\n#ifdef CW_USE_NAMED_SEMAPHORES\n\tif (semPtr == NULL || semPtr->semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#else\n\tif (semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n#endif\n\n\tCWDebugLog(\"Sem Timed Wait\");\n\n\ttime(&t);\n\n\ttimeout.tv_sec = t + sec;\n\ttimeout.tv_nsec = nsec;\n\n#ifdef CW_USE_NAMED_SEMAPHORES\n\twhile (sem_timedwait(semPtr->semPtr, &timeout) < 0) {\n#else\n\twhile (sem_timedwait(semPtr, &timeout) < 0) {\n#endif\n\t\tif (errno == EINTR) {\n\t\t\tcontinue;\n\t\t} else if (errno == ETIMEDOUT) {\n\t\t\tCWDebugLog(\"sem_timedwait expired\");\n\t\t\treturn CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);\n\t\t} else {\n\t\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t\t}\n\t}\n\n#else\n\tfd_set fset;\n\tint r;\n\tstruct timeval timeout;\n\tchar dummy;\n\n\tif (semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Timed Sem Wait\");\n\n\tFD_ZERO(&fset);\n\tFD_SET((*semPtr)[0], &fset);\n\n\ttimeout.tv_sec = sec;\n\ttimeout.tv_usec = nsec / 1000;\n\n\tCWDebugLog(\"Timed Sem Wait Before Select\");\n\twhile ((r = select(((*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) <= 0) {\n\t\tCWDebugLog(\"Timed Sem Wait Select error\");\n\t\tif (r == 0) {\n\t\t\tCWDebugLog(\"Timed Sem Wait Timeout\");\n\t\t\treturn CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);\n\t\t} else if (errno == EINTR) {\n\t\t\ttimeout.tv_sec = sec;\n\t\t\ttimeout.tv_usec = nsec / 1000;\n\t\t\tcontinue;\n\t\t}\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\tCWDebugLog(\"Timed Sem Wait After Select\");\n\n\t// ready to read\n\n\twhile (read((*semPtr)[0], &dummy, 1) < 0) {\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\t// send ack (three-way handshake)\n\n\twhile (send((*semPtr)[0], &dummy, 1, 0) < 0) {\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWErrorRaiseSystemError(CW_ERROR_SENDING);\n\t}\n\n\ttimeout.tv_sec = 2;\n\ttimeout.tv_usec = 0;\n\n\tCWDebugLog(\"Timed Sem Wait Before Select 2\");\n\twhile ((r = select(((*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) <= 0) {\n\t\tCWDebugLog(\"Timed Sem Wait Select error 2\");\n\t\tif (r == 0) {\n\t\t\tCWDebugLog(\"Timed Sem Wait Timeout 2\");\n\t\t\treturn CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);\n\t\t} else if (errno == EINTR) {\n\t\t\ttimeout.tv_sec = 2;\n\t\t\ttimeout.tv_usec = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\tCWDebugLog(\"Timed Sem Wait After Select 2\");\n\n\t// read ack\n\n\twhile (read((*semPtr)[0], &dummy, 1) < 0) {\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n#endif\n\n\tCWDebugLog(\"End of Timed Sem Wait\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWThreadTimedSemPost(CWThreadTimedSem * semPtr)\n{\n#ifdef HAVE_SEM_TIMEDWAIT\n\treturn CWThreadSemPost(semPtr);\n#else\n\tchar dummy = 'D';\n\tfd_set fset;\n\tint r;\n\tstruct timeval timeout;\n\n\tif (semPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Timed Sem Post\");\n\n\twhile (send((*semPtr)[1], &dummy, 1, 0) < 0) {\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWErrorRaiseSystemError(CW_ERROR_SENDING);\n\t}\n\n\t// read ack (three-way handshake)\n\n\tFD_ZERO(&fset);\n\tFD_SET((*semPtr)[1], &fset);\n\n\ttimeout.tv_sec = 2;\n\ttimeout.tv_usec = 0;\n\n\tCWDebugLog(\"Timed Sem Post Before Select\");\n\twhile ((r = select(((*semPtr)[1]) + 1, &fset, NULL, NULL, &timeout)) <= 0) {\n\t\tCWDebugLog(\"Timed Sem Post Select Error\");\n\t\tif (r == 0) {\t// timeout, server is not responding\n\t\t\t// note: this is not an error in a traditional semaphore, btw it's an error\n\t\t\t// according to our logic\n\t\t\tCWDebugLog(\"Timed Sem Post Timeout\");\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, \"Nobody is Waiting on this Sem\");\n\t\t} else if (errno == EINTR) {\n\t\t\ttimeout.tv_sec = 2;\n\t\t\ttimeout.tv_usec = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\tCWDebugLog(\"Timed Sem Post After Select\");\n\n\twhile (read((*semPtr)[1], &dummy, 1) < 0) {\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\t// send ack\n\twhile (send((*semPtr)[1], &dummy, 1, 0) < 0) {\n\t\tif (errno == EINTR)\n\t\t\tcontinue;\n\t\tCWErrorRaiseSystemError(CW_ERROR_SENDING);\n\t}\n\n\tCWDebugLog(\"End of Sem Post\");\n\n\treturn CW_TRUE;\n#endif\n}\n\n// wrappers for pthread_key_*()\nCWBool CWThreadCreateSpecific(CWThreadSpecific * specPtr, void (*destructor) (void *))\n{\n\tif (specPtr == NULL)\n\t\treturn CW_FALSE;\t// NULL destructor is allowed\n\n\tif (pthread_key_create(specPtr, destructor) != 0) {\n\t\tCWDebugLog(\"Error pthread key create\");\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\nvoid CWThreadDestroySpecific(CWThreadSpecific * specPtr)\n{\n\tif (specPtr == NULL)\n\t\treturn;\n\tpthread_key_delete(*specPtr);\n}\n\nvoid *CWThreadGetSpecific(CWThreadSpecific * specPtr)\n{\n\tif (specPtr == NULL)\n\t\treturn NULL;\n\treturn pthread_getspecific(*specPtr);\n}\n\nCWBool CWThreadSetSpecific(CWThreadSpecific * specPtr, void *valPtr)\n{\n\tif (specPtr == NULL || valPtr == NULL)\n\t\treturn CW_FALSE;\n\n\tswitch (pthread_setspecific(*specPtr, valPtr)) {\n\tcase 0:\t\t// success\n\t\tbreak;\n\tcase ENOMEM:\n\t\treturn CW_FALSE;\n\tdefault:\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\n// terminate the calling thread\nvoid CWExitThread()\n{\n\tprintf(\"\\n*** Exit Thread ***\\n\");\n\n\tpthread_exit((void *)0);\n}\n\nvoid CWThreadSetSignals(int how, int num, ...)\n{\n\tsigset_t mask;\n\tva_list args;\n\n\tsigemptyset(&mask);\n\n\tva_start(args, num);\n\n\tfor (; num > 0; num--) {\n\t\tsigaddset(&mask, va_arg(args, int));\n\t}\n\n\tCWThreadSigMask(how, &mask, NULL);\n\n\tva_end(args);\n}\n\n// timers\ntypedef struct {\n\tCWThread *requestedThreadPtr;\n\tint signalToRaise;\n} CWThreadTimerArg;\n\nstruct {\n\tCWThreadSem requestServiceSem;\n\tCWThreadMutex requestServiceMutex;\n\tCWThreadSem serviceProvidedSem;\n\n\tint requestedSec;\n\tenum {\n\t\tCW_TIMER_REQUEST,\n\t\tCW_TIMER_CANCEL,\n\t\tCW_TIMER_NONE\n\t} requestedOp;\n\tCWThread *requestedThreadPtr;\n\tint signalToRaise;\n\n\tCWBool error;\n\n\tCWTimerID timerID;\n} gTimersData;\n\nvoid CWHandleTimer(CWTimerArg arg)\n{\n\n\tCWThreadTimerArg *a = (CWThreadTimerArg *) arg;\n\tCWThread requestedThreadPtr = *(a->requestedThreadPtr);\n\tint signalToRaise = a->signalToRaise;\n\n\tCWThreadSendSignal(requestedThreadPtr, signalToRaise);\n\tCWDebugLog(\"Timer Expired, Sent Signal(%d) to Thread: %08x\", signalToRaise, requestedThreadPtr);\n\n\tCW_FREE_OBJECT(a->requestedThreadPtr);\n\tCW_FREE_OBJECT(a);\n\n\treturn;\n}\n\nCWBool CWTimerRequest(int sec, CWThread * threadPtr, CWTimerID * idPtr, int signalToRaise)\n{\n\n\tCWThreadTimerArg *arg;\n\n\tCWDebugLog(\"Timer Request\");\n\tif (sec < 0 || threadPtr == NULL || idPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_OBJECT_ERR(arg, CWThreadTimerArg, return CW_FALSE;\n\t    );\n\tCW_CREATE_OBJECT_ERR(arg->requestedThreadPtr, CWThread, CW_FREE_OBJECT(arg);\n\t\t\t     return CW_FALSE;\n\t    );\n\tCW_COPY_MEMORY(arg->requestedThreadPtr, threadPtr, sizeof(CWThread));\n\targ->signalToRaise = signalToRaise;\n\n\tCWDebugLog(\"Timer Request: thread(%08x), signal(%d)\", *(arg->requestedThreadPtr), arg->signalToRaise);\n\n\tif ((*idPtr = timer_add(sec, 0, &CWHandleTimer, arg)) == -1) {\n\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\nvoid CWTimerFreeArg(CWTimerArg arg)\n{\n\n\tCWThreadTimerArg *a = (CWThreadTimerArg *) arg;\n\n\t/* LE-03-02-2010.01 */\n\tif (a == NULL)\n\t\treturn;\n\n\tCW_FREE_OBJECT(a->requestedThreadPtr);\n\tCW_FREE_OBJECT(a);\n\n\treturn;\n}\n\nCWBool CWTimerCancel(CWTimerID * idPtr)\n{\n\n\ttimer_rem(*idPtr, CWTimerFreeArg);\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "CWThread.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWThread_HEADER__\n#define __CAPWAP_CWThread_HEADER__\n\n#include \"CWErrorHandling.h\"\n#include <pthread.h>\n#include <limits.h>\n#include <semaphore.h>\n#include <time.h>\n#include \"timerlib.h\"\n\n#ifdef MACOSX\n/* Mac OS X */\n#define CW_USE_NAMED_SEMAPHORES\n#include <unistd.h>\ntypedef struct {\n\tsem_t *semPtr;\n} CWThreadSem;\n#include <sys/types.h>\n#include <sys/un.h>\n\n#define max(a,b) ( (a) > (b) ? (a) : (b) )\n\n#else\ntypedef sem_t CWThreadSem;\n#endif\n\n#ifdef HAVE_SEM_TIMEDWAIT\ntypedef CWThreadSem CWThreadTimedSem;\n#else\ntypedef int CWThreadTimedSem[2];\t/* pair of Unix Domain Socket */\n#endif\n\ntypedef pthread_t CWThread;\ntypedef pthread_mutex_t CWThreadMutex;\ntypedef pthread_cond_t CWThreadCondition;\ntypedef pthread_key_t CWThreadSpecific;\ntypedef pthread_once_t CWThreadOnce;\n\ntypedef void *(*CW_THREAD_FUNCTION) (void *);\ntypedef int CWThreadId;\n\ntypedef int CWTimerID;\ntypedef void *CWTimerArg;\n\n#define CW_THREAD_RETURN_TYPE           void*\n#define CWThreadSigMask(how, set, old_set)  pthread_sigmask(how, set, old_set)\n#define CWThreadIsEqual(t1, t2)         pthread_equal(t1,t2)\n#define CWThreadSelf()              pthread_self()\n#define CWThreadKill(t1, signal)        pthread_kill(t1,signal)\n#define CWThreadSendSignal          CWThreadKill\n#define CW_THREAD_ONCE_INIT         PTHREAD_ONCE_INIT\n#define CWThreadCallOnce            pthread_once\n\nsem_t *CWThreadGetSemT(CWThreadSem * semPtr);\n\nCWBool CWThreadInitLib(void);\n\nCWBool CWCreateThread(CWThread * newThread, CW_THREAD_FUNCTION threadFunc, void *arg);\n\nCWBool CWCreateThreadCondition(CWThreadCondition * theCondition);\nvoid CWDestroyThreadCondition(CWThreadCondition * theCondition);\n\nCWBool CWWaitThreadCondition(CWThreadCondition * theCondition, CWThreadMutex * theMutex);\n\nCWBool CWWaitThreadConditionTimeout(CWThreadCondition * theCondition,\n\t\t\t\t    CWThreadMutex * theMutex, struct timespec *pTimeout);\n\nvoid CWSignalThreadCondition(CWThreadCondition * theCondition);\nCWBool CWCreateThreadMutex(CWThreadMutex * theMutex);\nvoid CWDestroyThreadMutex(CWThreadMutex * theMutex);\nCWBool CWThreadMutexLock(CWThreadMutex * theMutex);\nCWBool CWThreadMutexTryLock(CWThreadMutex * theMutex);\nvoid CWThreadMutexUnlock(CWThreadMutex * theMutex);\n\nCWBool CWThreadCreateSem(CWThreadSem * semPtr, int value);\nvoid CWThreadDestroySem(CWThreadSem * semPtr);\nCWBool CWThreadSemWait(CWThreadSem * semPtr);\nCWBool CWThreadSemPost(CWThreadSem * semPtr);\nCWBool CWThreadSemGetValue(CWThreadSem * semPtr, int *valuePtr);\n\nCWBool CWThreadCreateSpecific(CWThreadSpecific * specPtr, void (*destructor) (void *));\n\nvoid CWThreadDestroySpecific(CWThreadSpecific * specPtr);\nvoid *CWThreadGetSpecific(CWThreadSpecific * specPtr);\nCWBool CWThreadSetSpecific(CWThreadSpecific * specPtr, void *valPtr);\n\nvoid CWExitThread(void);\n\n//void *CWThreadManageTimers(void *arg);\nCWBool CWTimerCancel(CWTimerID * idPtr);\nCWBool CWTimerRequest(int sec, CWThread * threadPtr, CWTimerID * idPtr, int signalToRaise);\n\nvoid CWThreadSetSignals(int how, int num, ...);\n\nCWBool CWThreadCreateTimedSem(CWThreadTimedSem * semPtr, int value);\nCWBool CWThreadTimedSemIsZero(CWThreadTimedSem * semPtr);\nCWBool CWThreadTimedSemSetValue(CWThreadTimedSem * semPtr, int value);\nvoid CWThreadDestroyTimedSem(CWThreadTimedSem * semPtr);\nCWBool CWThreadTimedSemWait(CWThreadTimedSem * semPtr, time_t sec, time_t nsec);\nCWBool CWThreadTimedSemPost(CWThreadTimedSem * semPtr);\n\n#endif\n"
  },
  {
    "path": "CWTimer.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n/* This file implements routines for handling timeouts.\n *\n * User calls are:\n *   _clkini() - initialize clock and timers\n *   _setimr() - set a timer\n *   _cantim() - cancel a timer\n *   #disable_interrupts - disable clock and timer interrupts\n *   #enable_interrupts - enable clock and timer interrupts\n *\n *\n * History:\n *     Originally written for standalone MC68000 with MC6840 timer\n *     Ed Barkmeyer, NBS, September 1983\n *\n *     Rewritten for 4.2BSD UNIX with software timer.\n *     Don Libes, NBS, October 1985\n *\n */\n\n#include \"CWCommon.h\"\n\n#include <signal.h>\n#include <sys/time.h>\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#ifndef TRUE\n#define TRUE    1\n#define FALSE   0\n#endif\n\ntypedef short int int2;\ntypedef int int4;\n#define TIMER_SIGNAL_TYPE       CW_TIMER_INTERNAL_SIGNAL\n#define TIMER_INTERVAL_TYPE     ITIMER_REAL\nstruct itimerval timer_value;\n\nstatic unsigned timer_set_timestamp;\t/* this holds the value of */\n/* current_time() whenever an */\n/* interval timer is started */\n/* The following definitions support conversions between the basic unit of\ntime in the nip (which is tens-of-milliseconds) and time in all the 4.2BSD\nsystem calls (which is seconds and microseconds).\n*/\n#define USECS_PER_MSEC          1000\n#define MSECS_PER_SEC           1000\n#define USECS_PER_SEC           1000000\n#define MANY_TENS_OF_MSECS      (~0)\t/* unsigned, please */\n/* useful for converting from 4.2BSD to nip units */\n#define USECS_PER_TEN_MSECS     (USECS_PER_MSEC*10)\n#define TENS_OF_MSECS_PER_SEC   (MSECS_PER_SEC/10)\n/* useful for converting from nip units to 4.2 units */\n#define SEC(x)                  (x/TENS_OF_MSECS_PER_SEC)\n#define USEC(x)                 ((x*USECS_PER_TEN_MSECS)%USECS_PER_SEC)\n/*\nA timer wakeup queue should be represented as a data structure that can\ndo\nMIN, INSERT, DELETE and TRAVERSE operations in minimal time.\n INSERT and\nDELETE are necessary to support declaring and cancelling of timers MIN\nis\nnecessary to find out who has timed out and to decide what the next\ninterval\nto timeout should be.  TRAVERSE is necessary for updating all the\ntimers once\na time period has elapsed.  Unfortunately, I forget what this optimal data\nstructure is.  Until I remember, we shall use an array.\nThe array is used as follows:  Each entry in the array has a timeout.\nWe will constantly be waiting for the entry with the shortest timeout.\nWhen that times out, we will subtract from each timer's timeout, the time\nthat\nhas passed since we first started waiting for the current timer.\nWhen a timeout occurs, the event flag is set.  A timer is released from\nuse when the timeout is 0 AND the event flag points to 0.\n*/\n\n#define timer_inuse(t)  (t->timeout || t->event)\nstruct timer {\n\tunsigned int timeout;\t/* clock ticks to wait for */\n\tint2 *event;\t\t/* set to TRUE when time out occurs */\n\tvoid (*ast) (void *, int);\n\tCWTimerArg myArg;\n} timerq[CW_TIMER_MAX];\t\t/* timer queue */\nstruct timer *next_timer;\t/* timer we expect to run down next */\nstruct timer *shortest_timer();\nint oldmask;\t\t\t/* signal mask */\nsigset_t mask;\n\n/* actually these just fiddle with the interrupt from the timer */\n#define disable_interrupts()    pthread_sigmask(SIG_BLOCK, &mask, NULL);\t//oldmask = sigblock(1<<(TIMER_SIGNAL_TYPE-1))\n\n#define enable_interrupts()    pthread_sigmask(SIG_UNBLOCK, &mask, NULL);\n\n/* used when cancelling timers (if that works) */\nstruct itimerval cancel_timer = { {0, 0}, {0, 0} };\n\nvoid _clkini();\nint _setimr(unsigned int timeout, int2 * event, void (*ast) (void *, int), CWTimerArg myArg, int4 arg, char *pname,\n\t    CWTimerID * idPtr);\nint _cantim(CWTimerID * idPtr);\nvoid start_timer(struct timer *t);\nvoid cancel_itimer();\nvoid update_all_timers_by(unsigned int time);\n\n__inline__ CWBool CWTimersInitLib()\n{\n\tsigemptyset(&mask);\n\tsigaddset(&mask, SIGALRM);\n\tenable_interrupts();\n\t_clkini();\n\n\treturn CW_TRUE;\n}\n\nvoid CWTimersInit()\n{\n\tmemset(timerq, 0, sizeof(struct timer) * CW_TIMER_MAX);\n}\n\n// create a timer that expires after sec seconds. ID of the timer will be returned in *idPtr,\n// hdl() will be called with argument arg when the timer expires.\n__inline__ CWBool CWTimerCreate(int sec, CWTimerID * idPtr, void (*hdl) (CWTimerArg, CWTimerID), CWTimerArg arg)\n{\n\tint2 ev;\n\tif (idPtr == NULL || hdl == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (_setimr(sec * 100, &ev, (void *)hdl, arg, 0, NULL, idPtr) == -1) {\n\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"Out of Timers\");\n\t}\n\n\treturn CW_TRUE;\n}\n\n__inline__ CWTimerArg CWTimerGetArg(CWTimerID * idPtr)\n{\n\tCWTimerArg pResult;\n\n\tif (idPtr == NULL) {\n\t\tCWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t\treturn (CWTimerArg) NULL;\n\t}\n\t// From _cantim\n\tdisable_interrupts();\n\n\tpResult = timerq[*idPtr].myArg;\n\n\tenable_interrupts();\n\n\treturn pResult;\n}\n\n__inline__ CWBool CWTimerSetArg(CWTimerID * idPtr, CWTimerArg arg)\n{\n\tif (idPtr == NULL) {\n\t\tCWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t\treturn CW_FALSE;\n\t}\n\t// From _cantim\n\tdisable_interrupts();\n\n\ttimerq[*idPtr].myArg = arg;\n\n\tenable_interrupts();\n\n\treturn CW_TRUE;\n}\n\n__inline__ CWBool CWTimerDestroy(CWTimerID * idPtr)\n{\n\tif (idPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (_cantim(idPtr) == TRUE)\n\t\treturn CW_TRUE;\n\telse\n\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"Can't Destroy: Timer not Found\");\n}\n\n// CAPWAP note: don't use directly the following functions, just use the CWTimer*() wrappers\n\nvoid clk_isr();\nunsigned int current_time();\n\nstack_t new_stack;\nstruct sigaction siga;\n\n// init timers\nvoid _clkini()\n{\n\tstruct timer *t;\n\t/* disable constant interval timing */\n\ttimerclear(&timer_value.it_interval);\n\t/*\n\t   if (signal(TIMER_SIGNAL_TYPE, clk_isr) == SIG_ERR) {\n\t   perror(\"_clkini: signal failed\\n\");\n\t   exit(-1);\n\t   }\n\t */\n\tif ((new_stack.ss_sp = malloc(SIGSTKSZ)) == NULL) {\n\n\t\tperror(\"impossibile allocare memeoria per il nuovo stack\");\n\t}\n\n\tnew_stack.ss_size = SIGSTKSZ;\n\tnew_stack.ss_flags = 0;\n\n\tif (sigaltstack(&new_stack, NULL) < 0) {\n\n\t\tperror(\"sigaltstack\");\n\t}\n\n\tsiga.sa_handler = clk_isr;\n\tsigfillset(&siga.sa_mask);\n\tsiga.sa_flags = SA_ONSTACK;\n\n\tif (sigaction(TIMER_SIGNAL_TYPE, &siga, NULL)) {\n\n\t\tperror(\"_clkini: signal failed\\n\");\n\t\texit(-1);\n\t}\n\n\tfor (t = timerq; t < &timerq[CW_TIMER_MAX]; t++) {\n\t\tt->timeout = 0;\n\t\tt->event = 0;\n\t}\n}\n\nint _setimr(unsigned int timeout,\t/* time to wait in 10msec ticks */\n\t    int2 * event,\t/* event flag to set on runout */\n\t    void (*ast) (void *, int),\t/* routine to be called on runout or 0 */\n\t    CWTimerArg myArg, int4 arg,\t/* argument to be provided to timeout ast */\n\t    char *pname, CWTimerID * idPtr)\n{\n\tstruct timer *free_timer;\t/* pointer to unused timer entry */\n\tstruct timer *t;\n\t*event = 0;\n\n\tif (timeout == 0) {\t/* no time, so enable it and don't put on queue */\n\t\t*event = TRUE;\n\t\treturn (TRUE);\n\t}\n\tdisable_interrupts();\n\tfor (*idPtr = 0, t = timerq; t < &timerq[CW_TIMER_MAX]; t++, (*idPtr)++) {\n\t\tif (!timer_inuse(t)) {\n//                        CWDebugLog(\"Found free timer\");\n\t\t\tfree_timer = t;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (t == &timerq[CW_TIMER_MAX]) {\n\t\tCWDebugLog(\"Free timer not found\");\n\t\tenable_interrupts()\n\t\t    return -1;\t// out of timers\n\t}\n\n\t/* install new timer */\n\t/* cannot initialize free timer here, because cancel_itimer() will */\n\t/* munge with it, so push it into the branches of the the if */\n\n\tif (!next_timer) {\n//      CWDebugLog(\"First Timer\\n\");\n\t\t/* no timers set at all, so this is shortest */\n\t\tfree_timer->event = event;\n\t\tfree_timer->timeout = timeout;\n\t\tfree_timer->ast = ast;\n\t\tfree_timer->myArg = myArg;\n\t\tstart_timer(free_timer);\n\t} else if ((timeout + current_time()) < (next_timer->timeout + timer_set_timestamp)) {\n//              CWDebugLog(\"Shorter Timer\\n\");\n\t\t/* new timer is shorter than current one, so */\n\t\t/* cancel current timer and set up new one */\n\t\t/* not sure if the next setitimer() is actually necessary */\n\t\t/* probably not, but I haven't tested to make sure */\n\t\tcancel_itimer();\n\t\tfree_timer->event = event;\n\t\tfree_timer->timeout = timeout;\n\t\tfree_timer->ast = ast;\n\t\tfree_timer->myArg = myArg;\n\t\tstart_timer(free_timer);\n\t} else {\n\t\t/* new timer is longer, than current one */\n//      CWDebugLog(\"Longer Timer (%d)\\n\", timeout);\n\t\tfree_timer->event = event;\n\t\tfree_timer->timeout = timeout + (current_time() - timer_set_timestamp);\n\t\tfree_timer->ast = ast;\n\t\tfree_timer->myArg = myArg;\n\t}\n\n\tCWDebugLog(\"timer set, index:%d, timeout:%d\", *idPtr, timerq[*idPtr].timeout);\n\tenable_interrupts();\n\treturn (TRUE);\n}\n\n// cancel a timer\nint _cantim(CWTimerID * idPtr)\n{\n\tstruct timer *t;\n\n\tdisable_interrupts();\n\t// for (t=timerq;t<&timerq[CW_TIMER_MAX];t++) {\n\tt = &timerq[*idPtr];\n\t//if (t->event == event) {\n\tt->timeout = 0;\n\tt->event = 0;\n\tt->myArg = 0;\n\t/* check if we were waiting on this one */\n\tif (t == next_timer) {\n\t\tcancel_itimer();\n\t\tstart_timer(shortest_timer());\n\t}\n\tenable_interrupts();\n\treturn (TRUE);\n\t//}\n\t//}\n\tenable_interrupts();\n\treturn (FALSE);\n}\n\n/* clock interrupt handler */\n/* this routine is executed when an alarm signal occurs */\nvoid clk_isr()\n{\n\tCWDebugLog(\"Signal Timer Expired received\");\n\t/* the following condition could be set up,\n\t   if the interrupt was delivered while we were in cantim, cancelling\n\t   the last timer */\n\t//printf(\"\\n\\n\\n%d\\n\\n\", pthread_self());\n\tCWDebugLog(\"Subtract %d from timers\", current_time() - timer_set_timestamp);\n\tupdate_all_timers_by(current_time() - timer_set_timestamp);\n\tif (next_timer == 0)\n\t\treturn;\n\t/* start timer for next shortest guy if one exists */\n\tstart_timer(shortest_timer());\n}\n\n/* subtract time from all timers, enabling any that run out along the way */\nvoid update_all_timers_by(unsigned int time)\n{\n\tstruct timer *t;\n\tint id;\n\tCWDebugLog(\"Update Timers\");\n\tfor (id = 0, t = timerq; t < &timerq[CW_TIMER_MAX]; t++, id++) {\n\t\tif (t->timeout) {\n//          CWDebugLog(\"~~~~~~~~~timer set, index:%d, timeout:%d~~~~~~~~~~~~\", id, t->timeout);\n\t\t\tif (time < t->timeout) {\n\t\t\t\t//  CWDebugLog(\"timeout(%d) - time(%d)\\n\", t->timeout, time);\n\t\t\t\tt->timeout -= time;\n\t\t\t\t//  CWDebugLog(\"timeout(%d)\\n\", t->timeout);\n\t\t\t} else {\n\t\t\t\t//  CWDebugLog(\"(%d) %d vs %d\\n\", t, t->timeout, time);\n//              CWDebugLog(\"~~~~~~~è un segnale mio!~~~~~~~~~\");\n\t\t\t\tt->timeout = 0;\n\t\t\t\t(t->ast) ((void *)t->myArg, id);\n\t\t\t\t//  printf(\"%d vs %d\\n\", t->timeout, time);\n\t\t\t\t/* if this has forced a timeout on */\n\t\t\t\t/* anyone else, enable it */\n\t\t\t\t*t->event = TRUE;\n\t\t\t\tt->event = 0;\t/* remove timer */\n\t\t\t}\n\t\t}\n\t}\n}\n\nstruct timer *shortest_timer()\n{\n\tstruct timer *t, *s_t;\t/* shortest_timer */\n\tunsigned int old_timer = MANY_TENS_OF_MSECS;\n\tfor (s_t = 0, t = timerq; t < &timerq[CW_TIMER_MAX]; t++) {\n\t\tif (t->timeout > 0 && t->timeout < old_timer) {\n\t\t\told_timer = t->timeout;\n\t\t\ts_t = t;\n\t\t}\n\t}\n\treturn (s_t);\n}\n\nvoid start_timer(t)\nstruct timer *t;\n{\n\tnext_timer = t;\t\t/* remember for _cantim and _setimr */\n\tif (!t)\n\t\treturn;\n\ttimer_set_timestamp = current_time();\n\ttimer_value.it_value.tv_sec = SEC(next_timer->timeout);\n\ttimer_value.it_value.tv_usec = USEC(next_timer->timeout);\n//  CWDebugLog(\"Start System Timer (%d,%d)\", timer_value.it_value.tv_sec, timer_value.it_value.tv_usec);\n\tif (-1 == setitimer(TIMER_INTERVAL_TYPE, &timer_value, (struct itimerval *)0)) {\n\t\tperror(\"start_timer: setitimer\");\n\t\texit(-1);\n\t}\n}\n\n/* return time in tens of milliseconds */\nunsigned int current_time()\n{\n\tstruct timeval tp;\n\t(void)gettimeofday(&tp, (struct timezone *)0);\n\t/* ignore overflow */\n\treturn (tp.tv_sec * TENS_OF_MSECS_PER_SEC + tp.tv_usec / USECS_PER_TEN_MSECS);\n}\n\nvoid cancel_itimer()\n{\n\tif (-1 == setitimer(TIMER_INTERVAL_TYPE, &cancel_timer, (struct itimerval *)0)) {\n\t\tperror(\"_setimr: setitimer failed\");\n\t\texit(-1);\n\t}\n\tupdate_all_timers_by(current_time() - timer_set_timestamp);\n}\n"
  },
  {
    "path": "CWVendorPayloads.h",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap\n * Authors : Matteo Latini (mtylty@gmail.com)\n *       Donato Capitella (d.capitella@gmail.com)                                           *\n ************************************************************************************************/\n\n#ifndef __CAPWAP_VendorPayloads__\n#define __CAPWAP_VendorPayloads__\n\n/*#include \"CWCommon.h\"*/\n#include \"CWAC.h\"\n\n/***********************************************************************\n * Vendor specific payloads types\n * *********************************************************************/\n#define     CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI      1\n#define     CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM      2\n\n/***********************************************************************\n * UCI Server Port\n * *********************************************************************/\n#define UCI_SERVER_PORT 31337\n\ntypedef struct {\n\tunsigned char command;\n\tchar *commandArgs;\n\tchar *response;\n} CWVendorUciValues;\n\nCWBool CWParseVendorPayload(CWProtocolMessage * msg, int len, CWProtocolVendorSpecificValues * valPtr);\nCWBool CWParseUCIPayload(CWProtocolMessage * msg, CWVendorUciValues ** payloadPtr);\nCWBool CWWTPSaveUCIValues(CWVendorUciValues * uciPayload, CWProtocolResultCode * resultCode);\nCWBool CWAssembleWTPVendorPayloadUCI(CWProtocolMessage * msgPtr);\n\n/*************************************************************************\n *  WTP Update Messages\n *************************************************************************/\n\ntypedef struct {\n\tunsigned char major_v;\n\tunsigned char min_v;\n\tunsigned char revision;\n} mess_version_info;\ntypedef struct {\n\tmess_version_info v_info;\n\tunsigned int pack_size;\n} mess_up_req;\ntypedef struct {\n\tunsigned int seq_num;\n\tunsigned int size;\n\tunsigned char *buf;\n} mess_cup;\n\ntypedef struct {\n\tunsigned char type;\t/* Message type */\n\tunion {\n\t\tmess_version_info v_resp;\n\t\tmess_up_req up_req;\n\t\tmess_cup cup;\n\t} args;\n} CWVendorWumValues;\n\n#define _major_v_ args.v_resp.major_v\n#define _minor_v_ args.v_resp.min_v\n#define _revision_v_ args.v_resp.revision\n#define _pack_size_ args.up_req.pack_size\n#define _seq_num_ args.cup.seq_num\n#define _cup_ args.cup.buf\n#define _cup_fragment_size_ args.cup.size\n\n#define CUP_FRAGMENT_SIZE 4000\n\n//CWBool CWParseWUMPayload(CWProtocolMessage *msg, CWVendorUciValues **payloadPtr);\nCWBool CWWTPSaveWUMValues(CWVendorWumValues * wumPayload, CWProtocolResultCode * resultCode);\nCWBool CWAssembleWTPVendorPayloadWUM(CWProtocolMessage * msgPtr);\n\n#endif\n"
  },
  {
    "path": "CWVendorPayloadsAC.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Matteo Latini (mtylty@gmail.com)                                                   *\n *\n ************************************************************************************************/\n\n#include \"CWVendorPayloads.h\"\n#include \"WUM.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include <unistd.h>\n#include <signal.h>\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool CWAssembleWTPVendorPayloadUCI(CWProtocolMessage * msgPtr)\n{\n\tint *iPtr;\n\tunsigned short msgType;\n\tCWProtocolVendorSpecificValues *valuesPtr;\n\tCWVendorUciValues *uciPtr;\n\n\tCWLog(\"Assembling Protocol Configuration Update Request [VENDOR CASE]...\");\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\n\tvaluesPtr = gWTPs[*iPtr].vendorValues;\n\tswitch (valuesPtr->vendorPayloadType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\tmsgType = CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI;\n\t\tuciPtr = (CWVendorUciValues *) valuesPtr->payload;\n\t\tif (uciPtr->commandArgs != NULL) {\n\t\t\t/* create message */\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr,\n\t\t\t\t\t\t   sizeof(short) + sizeof(char) + sizeof(int) +\n\t\t\t\t\t\t   (strlen(uciPtr->commandArgs) * sizeof(char)),\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tCWProtocolStore16(msgPtr, (unsigned short)msgType);\n\t\t\tCWProtocolStore8(msgPtr, (unsigned char)uciPtr->command);\n\t\t\tCWProtocolStore32(msgPtr, (unsigned int)strlen(uciPtr->commandArgs));\n\t\t\tCWProtocolStoreStr(msgPtr, uciPtr->commandArgs);\n\t\t} else {\n\t\t\t/* create message */\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, sizeof(short) + sizeof(char) + sizeof(int),\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tCWProtocolStore16(msgPtr, (unsigned short)msgType);\n\t\t\tCWProtocolStore8(msgPtr, (unsigned char)uciPtr->command);\n\t\t\tCWProtocolStore32(msgPtr, 0);\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\treturn CW_FALSE;\n\t\tbreak;\n\t}\n\tCWLog(\"Assembling Protocol Configuration Update Request [VENDOR CASE]: Message Assembled.\");\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE);\n}\n\nCWBool CWAssembleWTPVendorPayloadWUM(CWProtocolMessage * msgPtr)\n{\n\tint *iPtr;\n\tunsigned short msgType;\n\tCWProtocolVendorSpecificValues *valuesPtr;\n\tCWVendorWumValues *wumPtr;\n\n\tCWLog(\"Assembling Protocol Configuration Update Request [VENDOR CASE]...\");\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\n\tvaluesPtr = gWTPs[*iPtr].vendorValues;\n\tswitch (valuesPtr->vendorPayloadType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\t/*\n\t\t * Here we assemble the WTP Update Messages.\n\t\t */\n\t\tmsgType = CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM;\n\t\twumPtr = (CWVendorWumValues *) valuesPtr->payload;\n\n\t\tswitch (wumPtr->type) {\n\t\tcase WTP_VERSION_REQUEST:\n\t\tcase WTP_COMMIT_UPDATE:\n\t\tcase WTP_CANCEL_UPDATE_REQUEST:\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, sizeof(short) + sizeof(char),\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tbreak;\n\t\tcase WTP_UPDATE_REQUEST:\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, sizeof(short) + 4 * sizeof(char) + sizeof(unsigned int),\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tbreak;\n\t\tcase WTP_CUP_FRAGMENT:\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr,\n\t\t\t\t\t\t   sizeof(short) + sizeof(char) + 2 * sizeof(int) +\n\t\t\t\t\t\t   wumPtr->_cup_fragment_size_,\n\t\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tCWLog(\"Error! unknown WUM message type!!!\");\n\t\t\treturn CW_FALSE;\n\t\t}\n\n\t\tCWProtocolStore16(msgPtr, (unsigned short)msgType);\n\t\tCWProtocolStore8(msgPtr, (unsigned char)wumPtr->type);\n\t\tif (wumPtr->type == WTP_UPDATE_REQUEST) {\n\t\t\tCWProtocolStore8(msgPtr, wumPtr->_major_v_);\n\t\t\tCWProtocolStore8(msgPtr, wumPtr->_minor_v_);\n\t\t\tCWProtocolStore8(msgPtr, wumPtr->_revision_v_);\n\t\t\tCWProtocolStore32(msgPtr, wumPtr->_pack_size_);\n\t\t} else if (wumPtr->type == WTP_CUP_FRAGMENT) {\n\t\t\tCWProtocolStore32(msgPtr, wumPtr->_seq_num_);\n\t\t\tCWProtocolStore32(msgPtr, wumPtr->_cup_fragment_size_);\n\t\t\tCWProtocolStoreRawBytes(msgPtr, wumPtr->_cup_, wumPtr->_cup_fragment_size_);\n\t\t\tCW_FREE_OBJECT(wumPtr->_cup_);\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\treturn CW_FALSE;\n\t\tbreak;\n\t}\n\tCWLog(\"Assembling Protocol Configuration Update Request [VENDOR CASE]: Message Assembled.\");\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE);\n}\n"
  },
  {
    "path": "CWVendorPayloadsWTP.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Matteo Latini (mtylty@gmail.com)\n *           Donato Capitella (d.capitella@gmail.com)\n *\n ************************************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include <unistd.h>\n#include <signal.h>\n#include <sys/stat.h>\n#include <sys/statvfs.h>\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#include \"CWWTP.h\"\n#include \"CWVendorPayloads.h\"\n#include \"WUM.h\"\n\nCWBool CWParseUCIPayload(CWProtocolMessage * msgPtr, CWVendorUciValues ** payloadPtr)\n{\n\tint argsLen;\n\tCWVendorUciValues *uciPayload = NULL;\n\n\tCW_CREATE_OBJECT_ERR(uciPayload, CWVendorUciValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tuciPayload->command = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\tuciPayload->response = NULL;\n\targsLen = (unsigned int)CWProtocolRetrieve32(msgPtr);\n\tif (argsLen != 0) {\n\t\tCW_CREATE_STRING_ERR(uciPayload->commandArgs, argsLen,\n\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tuciPayload->commandArgs = CWProtocolRetrieveStr(msgPtr, argsLen);\n\t} else\n\t\tuciPayload->commandArgs = NULL;\n\n\t*payloadPtr = uciPayload;\n\n\tCWLog(\"Parsed UCI Vendor Payload...\");\n\treturn CW_TRUE;\n}\n\nCWBool CWParseWUMPayload(CWProtocolMessage * msgPtr, CWVendorWumValues ** payloadPtr)\n{\n\tCWVendorWumValues *wumPayload = NULL;\n\n\tCW_CREATE_OBJECT_ERR(wumPayload, CWVendorWumValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\twumPayload->type = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\n\t/*\n\t * According to the type of the message, retrive additional fields\n\t */\n\tif (wumPayload->type == WTP_UPDATE_REQUEST) {\n\t\twumPayload->_major_v_ = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\t\twumPayload->_minor_v_ = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\t\twumPayload->_revision_v_ = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\t\twumPayload->_pack_size_ = (unsigned int)CWProtocolRetrieve32(msgPtr);\n\t} else if (wumPayload->type == WTP_CUP_FRAGMENT) {\n\t\twumPayload->_seq_num_ = (unsigned int)CWProtocolRetrieve32(msgPtr);\n\t\twumPayload->_cup_fragment_size_ = (unsigned int)CWProtocolRetrieve32(msgPtr);\n\t\twumPayload->_cup_ = CWProtocolRetrieveRawBytes(msgPtr, wumPayload->_cup_fragment_size_);\n\t}\n\n\t*payloadPtr = wumPayload;\n\n\tCWLog(\"Parsed WUM Vendor Payload...\");\n\treturn CW_TRUE;\n}\n\nCWBool CWParseVendorPayload(CWProtocolMessage * msgPtr, int len, CWProtocolVendorSpecificValues * valPtr)\n{\n\n\tCWVendorUciValues *uciPtr;\n\tCWVendorWumValues *wumPtr;\n\n\n\t/*...we choose which payload was used (in this case only\n\t   uci configuration payloads are used) */\n\tvalPtr->vendorPayloadType = (unsigned short)CWProtocolRetrieve16(msgPtr);\n\n\tswitch (valPtr->vendorPayloadType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\tif (!(CWParseUCIPayload(msgPtr, &uciPtr))) {\n\t\t\tCW_FREE_OBJECT(uciPtr->commandArgs);\n\t\t\tCW_FREE_OBJECT(uciPtr->response);\n\t\t\tCW_FREE_OBJECT(uciPtr);\n\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t}\n\t\tvalPtr->payload = (void *)uciPtr;\n\t\tbreak;\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\tif (!(CWParseWUMPayload(msgPtr, &wumPtr))) {\n\t\t\tCW_FREE_OBJECT(wumPtr);\n\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t}\n\t\tvalPtr->payload = (void *)wumPtr;\n\t\tbreak;\n\tdefault:\n\t\treturn CW_FALSE;\t// will be handled by the caller\n\t}\n\n\treturn CW_TRUE;\n}\n\n/************************************************************************\n * WTP Update System\n ************************************************************************/\n\n/* Update System States */\n#define WUM_STATE_WAIT  0\t/* waiting for WTP_UPDATE_REQUESTs */\n#define WUM_STATE_BUSY  1\t/* busy receiving CUP fragments */\n#define WUM_STATE_READY 2\t/* ready to start the update procedure */\n\nstruct WUMState {\n\tunsigned char state;\t/* one of the above states */\n\tFILE *cupTmp;\t\t/* pointer to the cup file */\n\tint cupSize;\t\t/* size of the cup file */\n\tint total_fragments;\t/* number of fragments of the cup file */\n\tint received_fragments;\t/* number of fragments already received */\n};\n\nstruct WUMState wumState = {\n\t.state = WUM_STATE_WAIT,\n\t.cupTmp = NULL,\n\t.cupSize = 0,\n\t.total_fragments = 0,\n\t.received_fragments = 0\n};\n\n#define CUP_TMP_FILE \"/tmp/wtp.cup\"\n#define WUA_BIN      \"WUA\"\n\n/*\n * WUMPrepareTmpFile\n *\n * After a WTP_UPDATE_REQUEST, calling this function prepares the update system\n * to accept CUP fragments and reassemble them into a temp file. If something goes\n * wrong, it returns CW_FALSE; otherwise it returns CW_TRUE, the wumState changes\n * to BUSY and we are ready to store the fragments we've received.\n */\nCWBool WUMPrepareForUpdate(int size)\n{\n\tif (wumState.state != WUM_STATE_WAIT) {\n\t\tCWLog(\"Can't start a new update session; the previous one isn't completed yet.\\n\");\n\t\treturn CW_FALSE;\n\t}\n\n\twumState.cupTmp = fopen(CUP_TMP_FILE, \"w\");\n\n\tif (wumState.cupTmp == NULL) {\n\t\tCWLog(\"Can't open temp file %s for writing.\\n\", CUP_TMP_FILE);\n\t\treturn CW_FALSE;\n\t}\n\n\twumState.cupSize = size;\n\twumState.total_fragments = size / CUP_FRAGMENT_SIZE;\n\tif (size % CUP_FRAGMENT_SIZE > 0)\n\t\twumState.total_fragments++;\n\twumState.received_fragments = 0;\n\n\twumState.state = WUM_STATE_BUSY;\n\n\treturn CW_TRUE;\n}\n\n/*\n * When in the BUSY State, this function is used to read and store the\n * fragments that compose the update package (CUP) into a temp file.\n */\nCWBool WUMStoreFragment(CWVendorWumValues * wumValues)\n{\n\tint offset, toWrite;\n\n\tif (wumState.state != WUM_STATE_BUSY) {\n\t\tCWLog(\"Received an update fragment, but no update session has been initialized yet.\\n\");\n\t\treturn CW_FALSE;\n\t}\n\n\tif (wumValues->_seq_num_ > wumState.total_fragments) {\n\t\tCWLog(\"Received an update fragment with invalid sequence number.\\n\");\n\t\treturn CW_FALSE;\n\t}\n\n\toffset = wumValues->_seq_num_ * CUP_FRAGMENT_SIZE;\n\n\tif (fseek(wumState.cupTmp, offset, SEEK_SET) != 0) {\n\t\tCWLog(\"Can't seek required offset in CUP tmp file.\\n\");\n\t\treturn CW_FALSE;\n\t}\n\n\ttoWrite = wumValues->_cup_fragment_size_;\n\tif (fwrite(wumValues->_cup_, 1, toWrite, wumState.cupTmp) != toWrite) {\n\t\tCWLog(\"Error while writing CUP tmp file.\\n\");\n\t\treturn CW_FALSE;\n\t}\n\n\tCW_FREE_OBJECT(wumValues->_cup_);\n\n\twumState.received_fragments++;\n\treturn CW_TRUE;\n}\n\n/*\n * Tells if all fragments of an update have been received and reassembled.\n */\nCWBool WUMIsComplete()\n{\n\tif (wumState.state != WUM_STATE_BUSY) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (wumState.total_fragments > wumState.received_fragments)\n\t\treturn CW_FALSE;\n\n\treturn CW_TRUE;\n}\n\n/*\n * Close the temp file and goes back to the READY State.\n */\nCWBool WUMCloseFile()\n{\n\tfclose(wumState.cupTmp);\n\twumState.cupTmp = NULL;\n\twumState.state = WUM_STATE_READY;\n\treturn CW_TRUE;\n}\n\n/*\n * Cancel an Update.\n */\nCWBool WUMCancel()\n{\n\twumState.state = WUM_STATE_WAIT;\n\tif (wumState.cupTmp)\n\t\tfclose(wumState.cupTmp);\n\twumState.cupTmp = NULL;\n\tremove(CUP_TMP_FILE);\n\treturn CW_TRUE;\n}\n\n/*\n * CWWTPCheckVersion - checks if we are already updated.\n */\nCWBool CWWTPCheckVersion(CWVendorWumValues * wumPayload)\n{\n\tint ret = CW_FALSE;\n\n\tif (wumPayload->_major_v_ > WTP_VERSION_MAJOR)\n\t\tret = CW_TRUE;\n\telse if (wumPayload->_major_v_ == WTP_VERSION_MAJOR) {\n\t\tif (wumPayload->_minor_v_ > WTP_VERSION_MINOR)\n\t\t\tret = CW_TRUE;\n\t\telse if (wumPayload->_minor_v_ == WTP_VERSION_MINOR) {\n\t\t\tif (wumPayload->_revision_v_ > WTP_VERSION_REVISION)\n\t\t\t\tret = CW_TRUE;\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nCWBool StartWUA()\n{\n\tint pid, fd;\n\tstruct flock fl;\n\n\t/* The following lock in set just for synchronization purposes */\n\tfl.l_type = F_WRLCK;\n\tfl.l_whence = SEEK_SET;\n\tfl.l_start = 0;\n\tfl.l_len = 0;\n\tfl.l_pid = getpid();\n\n\tfd = open(WTP_LOCK_FILE, O_CREAT | O_WRONLY, S_IRWXU);\n\n\tfcntl(fd, F_SETLKW, &fl);\t/* F_GETLK, F_SETLK, F_SETLKW */\n\n\tpid = fork();\n\tif (pid == 0) {\n\t\texecl(WUA_BIN, WUA_BIN, CUP_TMP_FILE, NULL);\n\t\texit(EXIT_FAILURE);\n\t} else if (pid < 0) {\n\t\tCWLog(\"Can't fork!\");\n\t\tclose(fd);\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\n/*\n * Returns CW_TRUE if the required space is available on the\n * filesystem where the /tmp dir is mounted.\n */\nCWBool check_free_space(int bytes)\n{\n\tstruct statvfs diskStat;\n\n\tif (statvfs(\"/tmp\", &diskStat) != 0) {\n\t\tCWLog(\"Can't stat filesystem!\\n\");\n\t\treturn CW_FALSE;\n\t}\n\n\tif (diskStat.f_bsize * diskStat.f_bfree > bytes)\n\t\treturn CW_TRUE;\n\n\treturn CW_FALSE;\n}\n\nCWBool CWWTPSaveWUMValues(CWVendorWumValues * wumPayload, CWProtocolResultCode * resultCode)\n{\n\t/* guards on input values */\n\tif (wumPayload == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tswitch (wumPayload->type) {\n\tcase WTP_VERSION_REQUEST:\n\t\twumPayload->type = WTP_VERSION_RESPONSE;\n\t\twumPayload->_major_v_ = WTP_VERSION_MAJOR;\n\t\twumPayload->_minor_v_ = WTP_VERSION_MINOR;\n\t\twumPayload->_revision_v_ = WTP_VERSION_REVISION;\n\t\tbreak;\n\tcase WTP_UPDATE_REQUEST:\n\t\t/* Check if update can be performed */\n\t\tCWLog(\"Received Update Request - Version %d.%d.%d\",\n\t\t      wumPayload->_major_v_, wumPayload->_minor_v_, wumPayload->_revision_v_);\n\n\t\twumPayload->type = WTP_UPDATE_RESPONSE;\n\n\t\tif (!CWWTPCheckVersion(wumPayload)) {\n\t\t\tCWLog(\"WTP already up to date.\\n\");\n\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t} else if (!check_free_space(wumPayload->_pack_size_)) {\n\t\t\tCWLog(\"No disk space available.\\n\");\n\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t} else if (WUMPrepareForUpdate(wumPayload->_pack_size_) == CW_FALSE) {\n\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t}\n\n\t\tbreak;\n\tcase WTP_CUP_FRAGMENT:\n\t\twumPayload->type = WTP_CUP_ACK;\n\n\t\tif (!WUMStoreFragment(wumPayload)) {\n\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t}\n\n\t\t/* if this is the last fragment, close temp file and\n\t\t * pass to the READY state. */\n\t\tif (WUMIsComplete()) {\n\t\t\tWUMCloseFile();\n\t\t}\n\t\tbreak;\n\tcase WTP_COMMIT_UPDATE:\n\t\twumPayload->type = WTP_COMMIT_ACK;\n\n\t\t/* Check if we are in the correct state */\n\t\tif (wumState.state != WUM_STATE_READY) {\n\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t}\n\n\t\t/* Start the Update Agent */\n\t\tStartWUA();\n\n\t\t/* Remember to exit after sending the WTP_COMMIT_ACK */\n\t\tWTPExitOnUpdateCommit = CW_TRUE;\n\t\tbreak;\n\tcase WTP_CANCEL_UPDATE_REQUEST:\n\t\twumPayload->type = WTP_CANCEL_UPDATE_RESPONSE;\n\n\t\tif (wumState.state == WUM_STATE_BUSY) {\n\t\t\t/* Accepting fragments */\n\t\t\tWUMCloseFile();\n\t\t\tif (!remove(CUP_TMP_FILE)) {\n\t\t\t\tCWLog(\"Error while removing cup tmp file.\");\n\t\t\t}\n\t\t} else if (wumState.state == WUM_STATE_READY) {\n\t\t\tif (!remove(CUP_TMP_FILE)) {\n\t\t\t\tCWLog(\"Error while removing cup tmp file.\");\n\t\t\t}\n\t\t}\n\t\twumState.state = WUM_STATE_WAIT;\n\t}\n\n\tCWLog(\"Saved WUM Vendor Payload...\");\n\treturn CW_TRUE;\n}\n\nCWBool CWWTPSaveUCIValues(CWVendorUciValues * uciPayload, CWProtocolResultCode * resultCode)\n{\n\n\tif (uciPayload == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tstruct sockaddr_in serv_addr;\n\tint sendSock, slen = sizeof(serv_addr), responseSize, responseCode;\n\tunsigned int ArgsSize, response = 0, ArgsSizeNet;\n\tchar *bufferMessage;\n\n\tif ((sendSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {\n\t\tCWLog(\"[CWSaveUCIValues]: Error on creation of socket.\");\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\tmemset(&serv_addr, 0, sizeof(serv_addr));\n\tserv_addr.sin_family = AF_INET;\n\tserv_addr.sin_port = htons(UCI_SERVER_PORT);\n\n\tif (inet_aton(\"127.0.0.1\", &serv_addr.sin_addr) == 0) {\n\t\tCWLog(\"[CWSaveUCIValues]: Error on aton function.\");\n\t\tclose(sendSock);\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\tif (uciPayload->commandArgs == NULL)\n\t\tArgsSize = 0;\n\telse\n\t\tArgsSize = strlen(uciPayload->commandArgs);\n\n\tif ((bufferMessage = malloc(ArgsSize + sizeof(unsigned char) + sizeof(unsigned int))) != NULL) {\n\t\tmemcpy(bufferMessage, &(uciPayload->command), sizeof(unsigned char));\t/* First Field */\n\t\tArgsSizeNet = htonl(ArgsSize);\n\t\tmemcpy(bufferMessage + sizeof(unsigned char), &ArgsSizeNet, sizeof(unsigned int));\t/* Second Field */\n\t\tif (uciPayload->commandArgs != NULL)\n\t\t\tmemcpy(bufferMessage + (sizeof(unsigned char) + sizeof(unsigned int)), uciPayload->commandArgs, ArgsSize);\t/* Third Field */\n\n\t\t/*Send conf request to uci daemon */\n\t\tif (sendto(sendSock, bufferMessage, sizeof(unsigned char), 0, (struct sockaddr *)&serv_addr, slen) < 0) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on sendto function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\t\tif (recvfrom\n\t\t    (sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,\n\t\t     (socklen_t *) & slen) < 0) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\n\t\tif (!ntohl(response)) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\t\tif (sendto\n\t\t    (sendSock, bufferMessage + sizeof(unsigned char), sizeof(unsigned int), 0,\n\t\t     (struct sockaddr *)&serv_addr, slen) < 0) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on sendto function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\n\t\tif (recvfrom\n\t\t    (sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,\n\t\t     (socklen_t *) & slen) < 0) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\n\t\tif (!ntohl(response)) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\t\tif (ArgsSize > 0) {\n\t\t\tif (sendto\n\t\t\t    (sendSock, bufferMessage + sizeof(unsigned char) + sizeof(unsigned int), ArgsSize, 0,\n\t\t\t     (struct sockaddr *)&serv_addr, slen) < 0) {\n\t\t\t\tCWLog(\"[CWSaveUCIValues]: Error on sendto function.\");\n\t\t\t\tclose(sendSock);\n\t\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t\t}\n\n\t\t\tif (recvfrom\n\t\t\t    (sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,\n\t\t\t     (socklen_t *) & slen) < 0) {\n\t\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\t\tclose(sendSock);\n\t\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t\t}\n\n\t\t\tif (!ntohl(response)) {\n\t\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\t\tclose(sendSock);\n\t\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tCWLog(\"[CWSaveUCIValues]: Error on malloc function.\");\n\t\tclose(sendSock);\n\t\tCW_FREE_OBJECT(bufferMessage);\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\t/*Receive result code from uci daemon */\n\tif (recvfrom\n\t    (sendSock, &responseCode, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,\n\t     (socklen_t *) & slen) < 0) {\n\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\tclose(sendSock);\n\t\tCW_FREE_OBJECT(bufferMessage);\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\tresponse = htonl(1);\n\n\tif (sendto(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr, slen) < 0) {\n\t\tCWLog(\"[CWSaveUCIValues]: Error on sendto function.\");\n\t\tclose(sendSock);\n\t\tCW_FREE_OBJECT(bufferMessage);\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\tresponseCode = ntohl(responseCode);\n\n\tif (responseCode != 0)\n\t\t/*If we have an error */\n\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\telse {\n\t\t/*OK, that's a go... receive response string (if we have it) */\n\t\t/*Receive response length from uci daemon */\n\t\tif (recvfrom\n\t\t    (sendSock, &responseSize, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,\n\t\t     (socklen_t *) & slen) < 0) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\n\t\tif (sendto(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr, slen) < 0) {\n\t\t\tCWLog(\"[CWSaveUCIValues]: Error on sendto function.\");\n\t\t\tclose(sendSock);\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t}\n\n\t\tresponseSize = ntohl(responseSize);\n\n\t\tif (responseSize > 0) {\n\n\t\t\tCW_FREE_OBJECT(bufferMessage);\n\n\t\t\t/*Fill buffer for response */\n\t\t\tif ((bufferMessage = malloc(responseSize * sizeof(unsigned char))) != NULL) {\n\n\t\t\t\t/*Receive from uci daemon the response string */\n\t\t\t\tif (recvfrom\n\t\t\t\t    (sendSock, bufferMessage, sizeof(unsigned char) * responseSize, 0,\n\t\t\t\t     (struct sockaddr *)&serv_addr, (socklen_t *) & slen) < 0) {\n\t\t\t\t\tCWLog(\"[CWSaveUCIValues]: Error on recvfrom function.\");\n\t\t\t\t\tclose(sendSock);\n\t\t\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t\t\t}\n\t\t\t\tif (sendto\n\t\t\t\t    (sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,\n\t\t\t\t     slen) < 0) {\n\t\t\t\t\tCWLog(\"[CWSaveUCIValues]: Error on sendto function.\");\n\t\t\t\t\tclose(sendSock);\n\t\t\t\t\tCW_FREE_OBJECT(bufferMessage);\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t\t\t}\n\n\t\t\t\t/*Copy the buffer in the uci payload structure */\n\t\t\t\tCW_CREATE_STRING_ERR(uciPayload->response, responseSize,\n\t\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\tmemcpy(uciPayload->response, bufferMessage, responseSize);\n\t\t\t\tuciPayload->response[responseSize] = '\\0';\n\n\t\t\t} else {\n\t\t\t\tCWLog(\"[CWSaveUCIValues]: Error on malloc function.\");\n\t\t\t\tclose(sendSock);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t\t\t}\n\t\t} else {\n\t\t\t/*If response is empty, set it to NULL (needed after, when the response is built) */\n\t\t\tuciPayload->response = NULL;\n\t\t}\n\t}\n\n\tCWLog(\"Saved UCI Vendor Payload...\");\n\tclose(sendSock);\n\tCW_FREE_OBJECT(bufferMessage);\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "CWWTP.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2005-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_CWWTP_HEADER__\n#define __CAPWAP_CWWTP_HEADER__\n\n/*_______________________________________________________*/\n/*  *******************___INCLUDE___*******************  */\n\n#include \"CWCommon.h\"\n#include \"WTPProtocol.h\"\n#include \"WTPBinding.h\"\n\n/*______________________________________________________*/\n/*  *******************___DEFINE___*******************  */\n#define WTP_LOG_FILE_NAME   \"/var/log/wtp.log.txt\"\n\n/*_____________________________________________________*/\n/*  *******************___TYPES___*******************  */\n\ntypedef struct {\n\tchar *address;\n\tCWBool received;\n\tint seqNum;\n} CWACDescriptor;\n\n/*_____________________________________________________________*/\n/*  *******************___WTP VARIABLES___*******************  */\nextern char *gInterfaceName;\nextern char *gEthInterfaceName;\nextern char *gRadioInterfaceName_0;\nextern char *gBaseMACInterfaceName;\nextern char gBoardReversionNo;\nextern char **gCWACAddresses;\nextern int gCWACCount;\n\nextern int gHostapd_port;\nextern char *gHostapd_unix_path;\nextern unsigned char gRADIO_MAC[6];\nextern pthread_mutex_t gRADIO_MAC_mutex;\n\nextern char *gWTPLocation;\nextern char *gWTPName;\nextern unsigned char gWTPSessionID[16];\nextern int gIPv4StatusDuplicate;\nextern int gIPv6StatusDuplicate;\nextern char *gWTPForceACAddress;\nextern CWAuthSecurity gWTPForceSecurity;\n\nextern CWSocket gWTPSocket;\nextern CWSocket gWTPDataSocket;\n\nextern int gWTPPathMTU;\n\nextern unsigned char gWTPMACMode;\nextern unsigned char gWTPTunnelMode;\n\nextern CWACDescriptor *gCWACList;\nextern CWACInfoValues *gACInfoPtr;\nextern CWStateTransition gWTPNextState;\nextern int gEchoInterval;\nextern int gWTPStatisticsTimer;\nextern WTPRebootStatisticsInfo gWTPRebootStatistics;\nextern CWWTPRadiosInfo gRadiosInfo;\nextern CWSecurityContext gWTPSecurityContext;\nextern CWSecuritySession gWTPSession;\n\nextern CWPendingRequestMessage gPendingRequestMsgs[MAX_PENDING_REQUEST_MSGS];\n\nextern CWSafeList gPacketReceiveList;\nextern CWSafeList gFrameList;\nextern CWThreadCondition gInterfaceWait;\nextern CWThreadMutex gInterfaceMutex;\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\n\n/* in WTP.c */\nCWBool CWWTPLoadConfiguration();\nCWBool CWWTPInitConfiguration();\nvoid CWWTPResetRadioStatistics(WTPRadioStatisticsInfo * radioStatistics);\nCWBool CWReceiveMessage(CWProtocolMessage * msgPtr);\nCWBool CWWTPSendAcknowledgedPacket(int seqNum,\n\t\t\t\t   CWList msgElemlist,\n\t\t\t\t   CWBool(assembleFunc) (CWProtocolMessage **, int *, int, int, CWList),\n\t\t\t\t   CWBool(parseFunc) (unsigned char *, int, int, void *),\n\t\t\t\t   CWBool(saveFunc) (void *), void *valuesPtr);\nvoid CWWTPDestroy();\n\n/* in WTPRunState.c */\nCWBool CWAssembleWTPDataTansferRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t       int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList);\n\nCWBool CWAssembleWTPEventRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList);\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveDtlsPacket(void *arg);\nCW_THREAD_RETURN_TYPE CWWTPReceiveDataPacket(void *arg);\nCWBool CWWTPCheckForBindingFrame();\n\n/* in WTPProtocol_User.c */\nCWBool CWWTPGetACNameWithIndex(CWACNamesWithIndex * ACsInfo);\nint getInterfaceMacAddr(char *interface, unsigned char *macAddr);\nint initWTPSessionID(unsigned char *sessionID);\nint CWWTPGetStatisticsTimer();\nvoid CWWTPGetIPv6Address(struct sockaddr_in6 *myAddr);\nCWBool CWGetWTPRadiosAdminState(CWRadiosAdminInfo * valPtr);\nCWBool CWGetDecryptErrorReport(int radioID, CWDecryptErrorReportInfo * valPtr);\n\n/* in WTPRetransmission.c */\nint CWSendPendingRequestMessage(CWPendingRequestMessage * pendingRequestMsgs,\n\t\t\t\tCWProtocolMessage * messages, int fragmentsNum);\n\nint CWFindPendingRequestMsgsBox(CWPendingRequestMessage * pendingRequestMsgs,\n\t\t\t\tconst int length, const int msgType, const int seqNum);\n\nvoid CWResetPendingMsgBox(CWPendingRequestMessage * pendingRequestMsgs);\nCWBool CWUpdatePendingMsgBox(CWPendingRequestMessage * pendingRequestMsgs,\n\t\t\t     unsigned char msgType,\n\t\t\t     int seqNum,\n\t\t\t     int timer_sec,\n\t\t\t     CWTimerArg timer_arg,\n\t\t\t     void (*timer_hdl) (CWTimerArg),\n\t\t\t     int retransmission, CWProtocolMessage * msgElems, int fragmentsNum);\n\n#ifdef SOFTMAC\n//in WTPmacDriverInteraction.c\nint set_wme_cwmin(int acclass, int value);\nint set_wme_cwmax(int acclass, int value);\nint set_wme_aifsn(int acclass, int value);\nint set_txq(int code, int cwmin, int cwmax, int aifs, int burst_time);\n\n\n#else\n\n#ifndef BCM\n//in WTPDriverInteraction.c\nint set_cwmin(int sock, struct iwreq wrq, int acclass, int sta, int value);\nint get_cwmin(int sock, struct iwreq *wrq, int acclass, int sta);\nint set_cwmax(int sock, struct iwreq wrq, int acclass, int sta, int value);\nint get_cwmax(int sock, struct iwreq *wrq, int acclass, int sta);\nint set_aifs(int sock, struct iwreq wrq, int acclass, int sta, int value);\nint get_aifs(int sock, struct iwreq *wrq, int acclass, int sta);\n\n#else\n\n//in WTPBcmDriverInteraction.c\nint set_wme_cwmin(int acclass, int value);\nint set_wme_cwmax(int acclass, int value);\nint set_wme_aifsn(int acclass, int value);\n#endif\n#endif\n\n/* in WTPDiscoveryState.c */\nCWStateTransition CWWTPEnterDiscovery();\nvoid CWWTPPickACInterface();\n\nCWStateTransition CWWTPEnterSulking();\nCWStateTransition CWWTPEnterJoin();\nCWStateTransition CWWTPEnterConfigure();\nCWStateTransition CWWTPEnterDataCheck();\nCWStateTransition CWWTPEnterRun();\n\nCWBool CWStartHeartbeatTimer();\nCWBool CWStopHeartbeatTimer();\nCWBool CWStartNeighborDeadTimer();\nCWBool CWStopNeighborDeadTimer();\nCWBool CWResetTimers();\n\nvoid CWWTPHeartBeatTimerExpiredHandler(void *arg);\nvoid CWWTPRetransmitTimerExpiredHandler(CWTimerArg arg);\n\nextern CWBool WTPExitOnUpdateCommit;\n\n#endif\n"
  },
  {
    "path": "Doxyfile",
    "content": "# Doxyfile 1.4.6\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\nPROJECT_NAME           = Capwap\nPROJECT_NUMBER         = \nOUTPUT_DIRECTORY       = /usr/local/src2/capwap/doxygen\nCREATE_SUBDIRS         = NO\nOUTPUT_LANGUAGE        = English\nUSE_WINDOWS_ENCODING   = NO\nBRIEF_MEMBER_DESC      = YES\nREPEAT_BRIEF           = YES\nABBREVIATE_BRIEF       = \"The $name class\" \\\n                         \"The $name widget\" \\\n                         \"The $name file\" \\\n                         is \\\n                         provides \\\n                         specifies \\\n                         contains \\\n                         represents \\\n                         a \\\n                         an \\\n                         the\nALWAYS_DETAILED_SEC    = NO\nINLINE_INHERITED_MEMB  = NO\nFULL_PATH_NAMES        = YES\nSTRIP_FROM_PATH        = /usr/local/src2/capwap/\nSTRIP_FROM_INC_PATH    = \nSHORT_NAMES            = NO\nJAVADOC_AUTOBRIEF      = NO\nMULTILINE_CPP_IS_BRIEF = NO\nDETAILS_AT_TOP         = NO\nINHERIT_DOCS           = YES\nSEPARATE_MEMBER_PAGES  = NO\nTAB_SIZE               = 8\nALIASES                = \nOPTIMIZE_OUTPUT_FOR_C  = NO\nOPTIMIZE_OUTPUT_JAVA   = NO\nBUILTIN_STL_SUPPORT    = NO\nDISTRIBUTE_GROUP_DOC   = NO\nSUBGROUPING            = YES\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\nEXTRACT_ALL            = YES\nEXTRACT_PRIVATE        = YES\nEXTRACT_STATIC         = YES\nEXTRACT_LOCAL_CLASSES  = YES\nEXTRACT_LOCAL_METHODS  = YES\nHIDE_UNDOC_MEMBERS     = NO\nHIDE_UNDOC_CLASSES     = NO\nHIDE_FRIEND_COMPOUNDS  = NO\nHIDE_IN_BODY_DOCS      = NO\nINTERNAL_DOCS          = NO\nCASE_SENSE_NAMES       = YES\nHIDE_SCOPE_NAMES       = NO\nSHOW_INCLUDE_FILES     = YES\nINLINE_INFO            = YES\nSORT_MEMBER_DOCS       = YES\nSORT_BRIEF_DOCS        = NO\nSORT_BY_SCOPE_NAME     = NO\nGENERATE_TODOLIST      = YES\nGENERATE_TESTLIST      = YES\nGENERATE_BUGLIST       = YES\nGENERATE_DEPRECATEDLIST= YES\nENABLED_SECTIONS       = \nMAX_INITIALIZER_LINES  = 30\nSHOW_USED_FILES        = YES\nSHOW_DIRECTORIES       = NO\nFILE_VERSION_FILTER    = \n#---------------------------------------------------------------------------\n# configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\nQUIET                  = NO\nWARNINGS               = YES\nWARN_IF_UNDOCUMENTED   = YES\nWARN_IF_DOC_ERROR      = YES\nWARN_NO_PARAMDOC       = NO\nWARN_FORMAT            = \"$file:$line: $text\"\nWARN_LOGFILE           = \n#---------------------------------------------------------------------------\n# configuration options related to the input files\n#---------------------------------------------------------------------------\nINPUT                  = /usr/local/src2/capwap\nFILE_PATTERNS          = *.c \\\n                         *.cc \\\n                         *.cxx \\\n                         *.cpp \\\n                         *.c++ \\\n                         *.d \\\n                         *.java \\\n                         *.ii \\\n                         *.ixx \\\n                         *.ipp \\\n                         *.i++ \\\n                         *.inl \\\n                         *.h \\\n                         *.hh \\\n                         *.hxx \\\n                         *.hpp \\\n                         *.h++ \\\n                         *.idl \\\n                         *.odl \\\n                         *.cs \\\n                         *.php \\\n                         *.php3 \\\n                         *.inc \\\n                         *.m \\\n                         *.mm \\\n                         *.dox \\\n                         *.py \\\n                         *.C \\\n                         *.CC \\\n                         *.C++ \\\n                         *.II \\\n                         *.I++ \\\n                         *.H \\\n                         *.HH \\\n                         *.H++ \\\n                         *.CS \\\n                         *.PHP \\\n                         *.PHP3 \\\n                         *.M \\\n                         *.MM \\\n                         *.PY\nRECURSIVE              = NO\nEXCLUDE                = \nEXCLUDE_SYMLINKS       = NO\nEXCLUDE_PATTERNS       = \nEXAMPLE_PATH           = \nEXAMPLE_PATTERNS       = *\nEXAMPLE_RECURSIVE      = NO\nIMAGE_PATH             = \nINPUT_FILTER           = \nFILTER_PATTERNS        = \nFILTER_SOURCE_FILES    = NO\n#---------------------------------------------------------------------------\n# configuration options related to source browsing\n#---------------------------------------------------------------------------\nSOURCE_BROWSER         = YES\nINLINE_SOURCES         = YES\nSTRIP_CODE_COMMENTS    = YES\nREFERENCED_BY_RELATION = YES\nREFERENCES_RELATION    = YES\nUSE_HTAGS              = NO\nVERBATIM_HEADERS       = YES\n#---------------------------------------------------------------------------\n# configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\nALPHABETICAL_INDEX     = NO\nCOLS_IN_ALPHA_INDEX    = 5\nIGNORE_PREFIX          = \n#---------------------------------------------------------------------------\n# configuration options related to the HTML output\n#---------------------------------------------------------------------------\nGENERATE_HTML          = YES\nHTML_OUTPUT            = html\nHTML_FILE_EXTENSION    = .html\nHTML_HEADER            = \nHTML_FOOTER            = \nHTML_STYLESHEET        = \nHTML_ALIGN_MEMBERS     = YES\nGENERATE_HTMLHELP      = NO\nCHM_FILE               = \nHHC_LOCATION           = \nGENERATE_CHI           = NO\nBINARY_TOC             = NO\nTOC_EXPAND             = YES\nDISABLE_INDEX          = NO\nENUM_VALUES_PER_LINE   = 4\nGENERATE_TREEVIEW      = YES\nTREEVIEW_WIDTH         = 250\n#---------------------------------------------------------------------------\n# configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\nGENERATE_LATEX         = NO\nLATEX_OUTPUT           = latex\nLATEX_CMD_NAME         = latex\nMAKEINDEX_CMD_NAME     = makeindex\nCOMPACT_LATEX          = NO\nPAPER_TYPE             = a4wide\nEXTRA_PACKAGES         = \nLATEX_HEADER           = \nPDF_HYPERLINKS         = NO\nUSE_PDFLATEX           = NO\nLATEX_BATCHMODE        = NO\nLATEX_HIDE_INDICES     = NO\n#---------------------------------------------------------------------------\n# configuration options related to the RTF output\n#---------------------------------------------------------------------------\nGENERATE_RTF           = NO\nRTF_OUTPUT             = rtf\nCOMPACT_RTF            = NO\nRTF_HYPERLINKS         = NO\nRTF_STYLESHEET_FILE    = \nRTF_EXTENSIONS_FILE    = \n#---------------------------------------------------------------------------\n# configuration options related to the man page output\n#---------------------------------------------------------------------------\nGENERATE_MAN           = NO\nMAN_OUTPUT             = man\nMAN_EXTENSION          = .3\nMAN_LINKS              = NO\n#---------------------------------------------------------------------------\n# configuration options related to the XML output\n#---------------------------------------------------------------------------\nGENERATE_XML           = NO\nXML_OUTPUT             = xml\nXML_SCHEMA             = \nXML_DTD                = \nXML_PROGRAMLISTING     = YES\n#---------------------------------------------------------------------------\n# configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\nGENERATE_AUTOGEN_DEF   = NO\n#---------------------------------------------------------------------------\n# configuration options related to the Perl module output\n#---------------------------------------------------------------------------\nGENERATE_PERLMOD       = NO\nPERLMOD_LATEX          = NO\nPERLMOD_PRETTY         = YES\nPERLMOD_MAKEVAR_PREFIX = \n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor   \n#---------------------------------------------------------------------------\nENABLE_PREPROCESSING   = YES\nMACRO_EXPANSION        = NO\nEXPAND_ONLY_PREDEF     = NO\nSEARCH_INCLUDES        = YES\nINCLUDE_PATH           = \nINCLUDE_FILE_PATTERNS  = \nPREDEFINED             = \nEXPAND_AS_DEFINED      = \nSKIP_FUNCTION_MACROS   = YES\n#---------------------------------------------------------------------------\n# Configuration::additions related to external references   \n#---------------------------------------------------------------------------\nTAGFILES               = \nGENERATE_TAGFILE       = \nALLEXTERNALS           = NO\nEXTERNAL_GROUPS        = YES\nPERL_PATH              = /usr/bin/perl\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool   \n#---------------------------------------------------------------------------\nCLASS_DIAGRAMS         = YES\nHIDE_UNDOC_RELATIONS   = YES\nHAVE_DOT               = YES\nCLASS_GRAPH            = YES\nCOLLABORATION_GRAPH    = YES\nGROUP_GRAPHS           = YES\nUML_LOOK               = NO\nTEMPLATE_RELATIONS     = NO\nINCLUDE_GRAPH          = YES\nINCLUDED_BY_GRAPH      = YES\nCALL_GRAPH             = YES\nGRAPHICAL_HIERARCHY    = YES\nDIRECTORY_GRAPH        = YES\nDOT_IMAGE_FORMAT       = png\nDOT_PATH               = \nDOTFILE_DIRS           = \nMAX_DOT_GRAPH_WIDTH    = 1024\nMAX_DOT_GRAPH_HEIGHT   = 1024\nMAX_DOT_GRAPH_DEPTH    = 1000\nDOT_TRANSPARENT        = NO\nDOT_MULTI_TARGETS      = NO\nGENERATE_LEGEND        = YES\nDOT_CLEANUP            = YES\n#---------------------------------------------------------------------------\n# Configuration::additions related to the search engine   \n#---------------------------------------------------------------------------\nSEARCHENGINE           = NO\n"
  },
  {
    "path": "INSTALL.rst",
    "content": "=============================================\nHOW TO BUILD AND RUN CAPWAP FOR LINUX SYSTEMS\n=============================================\n\nNOTE: To run WTP you must have a wireless card that has Linux driver based on the\n      Generic IEEE 802.11 Networking Stack (mac80211).\n\n\nHOW TO BUILD AC AND WTP\n=======================\n\nRequirements\n------------\n\n* automake 1.9 or newer\n* autoconf\n* libtool\n* openssl\n\nBuild\n-----\n\nRun:\n\n  autoreconf -f -i -s\n  CFLAGS=\"-I/usr/include/openssl -DLOCALUDP\" ./configure\n  make\n  make install\n\nUse the CFLAGS setting \"-DLOCALUDP\" to use local UNIX sockets for\nhostapd to AC/WTP communication. The openssl include path needs to\nbe adjusted to your local openssl installation directory.\n\nHOW TO RUN WTP\n==============\n\n* build hostapd with capwap support, see hostapd_wrapper/README.rst for instructions\n* make sure that your PCMCIA wireless card is working\n\n* create a wireless interfaces on the WiFi card in \"ap\" mode,\n  /usr/sbin/iw phy phy0 interface add wlan0 type managed\n* adjust settings.wtp.txt and config.wtp\n* run WTP in superuser mode\n* run hostapd (see also hostapd_wrapper/README.rst)\n\nHOW TO RUN AC\n=============\n\n* build hostapd with capwap support, see hostapd_wrapper/README.rst for instructions\n\n\n* adjust settings.ac.txt and config.ac\n* run AC in superuser mode\n* run hostapd (see also hostapd_wrapper/README.rst)\n"
  },
  {
    "path": "Makefile.am",
    "content": "ACLOCAL_AMFLAGS=-I m4\n\nAM_CPPFLAGS = -I$(srcdir)/include -D_REENTRANT\nAM_CPPFLAGS += -DOPENSSL_NO_KRB5\n\n# Capwap Debugging\nAM_CPPFLAGS += -DWRITE_STD_OUTPUT\nAM_CPPFLAGS += -DSOFTMAC\nAM_CPPFLAGS += -Wall\n\nbin_PROGRAMS = AC WTP WUA\n\nnoinst_LTLIBRARIES = libcapwap.la\nlibcapwap_la_SOURCES = \\\n\tCWLog.c \\\n\tCWCommon.c \\\n\tCWConfigFile.c \\\n\tCWErrorHandling.c \\\n\tCWList.c \\\n\tCWSafeList.c \\\n\tCWNetwork.c \\\n\tCWProtocol.c \\\n\tCWRandom.c \\\n\tCWStevens.c \\\n\tCWThread.c \\\n\tCWBinding.c \\\n\tCWVendorPayloadsAC.c \\\n\tCWVendorPayloadsWTP.c \\\n\ttimerlib.c\n\nif USE_SSL\nlibcapwap_la_SOURCES += \\\n\tCWSecurity.c \\\n\tCWOpenSSLBio.c\nendif\n\nlibcapwap_la_CFLAGS = ${OPENSSL_INCLUDES}\nlibcapwap_la_LIBADD = ${OPENSSL_LDFLAGS} ${OPENSSL_LIBS}\n\nAC_SOURCES = \\\n\tAC.c \\\n\tACConfigFile.c \\\n\tACMainLoop.c \\\n\tACDiscoveryState.c \\\n\tACJoinState.c \\\n\tACConfigureState.c \\\n\tACDataCheckState.c \\\n\tACRunState.c \\\n\tACProtocol_User.c \\\n\tACRetransmission.c \\\n\tACMultiHomedSocket.c \\\n\tACProtocol.c \\\n\tACBinding.c \\\n\tACInterface.c \\\n\tACSettingsFile.c \\\n\ttap.c \\\n\tACipcHostapd.c\nAC_LDADD = libcapwap.la\n\nWTP_SOURCES = \\\n\tWTP.c \\\n\tWTPipcHostapd.c \\\n\tWTPmacFrameReceive.c \\\n\tWTPFreqStatsReceive.c \\\n\tWTPStatsReceive.c \\\n\tWTPConfigFile.c \\\n\tWTPProtocol.c \\\n\tWTPProtocol_User.c \\\n\tWTPDiscoveryState.c \\\n\tWTPJoinState.c \\\n\tWTPConfigureState.c \\\n\tWTPDataCheckState.c \\\n\tWTPRunState.c \\\n\tWTPRunStateCheck.c \\\n\tWTPRetransmission.c \\\n\tWTPSulkingState.c \\\n\tWTPBinding.c \\\n\tWTPmacDriverInteraction.c \\\n\tWTPSettingsFile.c\nWTP_LDADD = libcapwap.la\n\nWUA_SOURCES = WUA.c\n"
  },
  {
    "path": "Makefile.bcm",
    "content": "# *******************************************************************************************\n# * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n# *                      Universita' Campus BioMedico - Italy                               *\n# *                                                                                         *\n# * This program is free software; you can redistribute it and/or modify it under the terms *\n# * of the GNU General Public License as published by the Free Software Foundation; either  *\n# * version 2 of the License, or (at your option) any later version.                        *\n# *                                                                                         *\n# * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n# * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n# * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n# *                                                                                         *\n# * You should have received a copy of the GNU General Public License along with this       *\n# * program; if not, write to the:                                                          *\n# * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n# * MA  02111-1307, USA.                                                                    *\n# *                                                                                         *\n# * --------------------------------------------------------------------------------------- *\n# * Project:  Capwap                                                                        *\n# *                                                                                         *\n# * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *  \n# *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n# *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n# *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n# *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n# *******************************************************************************************\n\nKAMIKAZEDIR=/home/daniele/Scrivania/kamikaze-SDK\n\nCC = $(KAMIKAZEDIR)/staging_dir_mipsel/bin/mipsel-linux-gcc \n\nLDFLAGS =  $(KAMIKAZEDIR)/staging_dir_mipsel/usr/lib/libssl.a  $(KAMIKAZEDIR)/staging_dir_mipsel/usr/lib/libcrypto.a  $(KAMIKAZEDIR)/staging_dir_mipsel/lib/libpthread.a  $(KAMIKAZEDIR)/staging_dir_mipsel/lib/libdl.a $(KAMIKAZEDIR)/staging_dir_mipsel/usr/lib/libpcap.a -D_REENTRANT\n\nCFLAGS = -Wall -g -O0 -D_REENTRANT -DBCM -I $(KAMIKAZEDIR)/staging_dir_mipsel/usr/include #-DCW_NO_DTLS\n\n# Memory leak\n#LDFLAGS += ../dmalloc-5.5.0/libdmallocth.a\n#CFLAGS += -DDMALLOC\n\n# Capwap Debugging\nCFLAGS += -DCW_DEBUGGING\n\nRM = /bin/rm -f \n\n# list of generated object files for WTP. \nWTP_OBJS = WTP.o WTPBcmFrameReceive.o WTPConfigFile.o WTPProtocol.o WTPProtocol_User.o WTPDiscoveryState.o WTPJoinState.o WTPConfigureState.o WTPDataCheckState.o WTPRunState.o WTPRunStateCheck.o WTPRetransmission.o WTPSulkingState.o CWCommon.o CWConfigFile.o CWErrorHandling.o CWSafeList.o CWList.o CWLog.o CWNetwork.o CWProtocol.o CWRandom.o CWSecurity.o CWOpenSSLBio.o CWStevens.o CWThread.o CWBinding.o WTPBinding.o WTPBcmDriverInteraction.o WTPSettingsFile.o timerlib.o\n \nWTP_SRCS = $(WTP_OBJS:.o=.c)\n\nWTP_DEPS := $(WTP_OBJS:.o=.d)\n\n# program executables. \nWTP_NAME = WTP \n\n.PHONY: deps clean clean_libs libs\n\n# top-level rule, to compile everything. \nall: $(WTP_NAME)\n\n$(WTP_NAME): $(WTP_OBJS) \n    $(CC) -DWRITE_STD_OUTPUT $(WTP_OBJS) $(CC_FLAGS) $(LDFLAGS) -o $(WTP_NAME) \n\nclean: \n    $(RM) $(WTP_NAME) $(WTP_OBJS) $(WTP_DEPS)\n\nclean_deps:\n    $(WTP_DEPS)\n    \ndeps: $(WTP_SRC)\n    $(CC) -MD -E -DWRITE_STD_OUTPUT $(WTP_SRCS) $(CFLAGS) >/dev/null\n\n-include $(WTP_DEPS)\n"
  },
  {
    "path": "Makefile.glibc",
    "content": "# *******************************************************************************************\n# * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n# *                      Universita' Campus BioMedico - Italy                               *\n# *                                                                                         *\n# * This program is free software; you can redistribute it and/or modify it under the terms *\n# * of the GNU General Public License as published by the Free Software Foundation; either  *\n# * version 2 of the License, or (at your option) any later version.                        *\n# *                                                                                         *\n# * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n# * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n# * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n# *                                                                                         *\n# * You should have received a copy of the GNU General Public License along with this       *\n# * program; if not, write to the:                                                          *\n# * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n# * MA  02111-1307, USA.                                                                    *\n# *                                                                                         *\n# * --------------------------------------------------------------------------------------- *\n# * Project:  Capwap                                                                        *\n# *                                                                                         *\n# * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *  \n# *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n# *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n# *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n# *******************************************************************************************\n\n\n\nCC = gcc \n\n#LDFLAGS = -lssl -lcrypto -lpthread -ldl -D_REENTRANT\n#LDFLAGS = /usr/lib/libefence.a ./static/libssl.a ./static/libcrypto.a -lpthread -ldl -D_REENTRANT\nLDFLAGS = ./static/libssl.a ./static/libcrypto.a -lpthread -ldl -D_REENTRANT\n\nCFLAGS = -Wall -g -O0 -D_REENTRANT -I/usr/local/ssl/include/ #-DCW_NO_DTLS\n\nOPENSSL_INCLUDE = #-I/usr/local/ssl/include/ #Openssl include files\n\n# Memory leak\n#LDFLAGS += ../dmalloc-5.5.0/libdmallocth.a\n#CFLAGS += -DDMALLOC\n\n# Capwap Debugging\nCFLAGS += -DCW_DEBUGGING\n\nRM = /bin/rm -f \n\n# list of generated object files for AC. \nAC_OBJS = AC.o ACConfigFile.o ACMainLoop.o ACDiscoveryState.o ACJoinState.o ACConfigureState.o ACDataCheckState.o ACRunState.o ACProtocol_User.o ACRetransmission.o CWCommon.o CWConfigFile.o CWErrorHandling.o CWList.o CWLog.o ACMultiHomedSocket.o  ACProtocol.o CWSafeList.o CWNetwork.o CWProtocol.o CWRandom.o CWSecurity.o CWOpenSSLBio.o CWStevens.o CWThread.o CWBinding.o CWVendorPayloadsAC.o ACBinding.o ACInterface.o ACSettingsFile.o timerlib.o \n\n# list of generated object files for WTP. \nWTP_OBJS = WTP.o WTPFrameReceive.o WTPFreqStatsReceive.o WTPStatsReceive.o WTPConfigFile.o WTPProtocol.o WTPProtocol_User.o WTPDiscoveryState.o WTPJoinState.o WTPConfigureState.o WTPDataCheckState.o WTPRunState.o WTPRunStateCheck.o WTPRetransmission.o WTPSulkingState.o CWCommon.o CWConfigFile.o CWErrorHandling.o CWSafeList.o CWList.o CWLog.o CWNetwork.o CWProtocol.o CWRandom.o CWSecurity.o CWOpenSSLBio.o CWStevens.o CWThread.o CWBinding.o CWVendorPayloadsWTP.o WTPBinding.o WTPDriverInteraction.o WTPSettingsFile.o timerlib.o\n \nAC_SRCS = $(AC_OBJS:.o=.c) \nWTP_SRCS = $(WTP_OBJS:.o=.c)\n\nAC_DEPS := $(AC_OBJS:.o=.d)\nWTP_DEPS := $(WTP_OBJS:.o=.d)\n\n# program executables. \nAC_NAME = AC \nWTP_NAME = WTP \n\n.PHONY: deps clean clean_libs libs\n\n# top-level rule, to compile everything. \nall: $(AC_NAME) $(WTP_NAME)\n\n$(AC_NAME): $(AC_OBJS) \n    $(CC) $(AC_OBJS) $(CC_FLAGS) $(OPENSSL_INCLUDE) $(LDFLAGS) -o $(AC_NAME) \n\n$(WTP_NAME): $(WTP_OBJS) \n    $(CC) -DWRITE_STD_OUTPUT $(WTP_OBJS) $(CC_FLAGS) $(LDFLAGS) -o $(WTP_NAME) \n\nclean: \n    $(RM) $(AC_NAME) $(WTP_NAME) $(AC_OBJS) $(WTP_OBJS) $(AC_DEPS) $(WTP_DEPS)\n\nclean_deps:\n    $(AC_DEPS) $(WTP_DEPS)\n    \ndeps: $(AC_SRC) $(WTP_SRC)\n    $(CC) -MD -E $(AC_SRCS) $(CFLAGS) >/dev/null\n    $(CC) -MD -E -DWRITE_STD_OUTPUT $(WTP_SRCS) $(CFLAGS) >/dev/null\n\n-include $(AC_DEPS)\n-include $(WTP_DEPS)\n"
  },
  {
    "path": "Makefile.uclibc",
    "content": "# *******************************************************************************************\n# * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n# *                      Universita' Campus BioMedico - Italy                               *\n# *                                                                                         *\n# * This program is free software; you can redistribute it and/or modify it under the terms *\n# * of the GNU General Public License as published by the Free Software Foundation; either  *\n# * version 2 of the License, or (at your option) any later version.                        *\n# *                                                                                         *\n# * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n# * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n# * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n# *                                                                                         *\n# * You should have received a copy of the GNU General Public License along with this       *\n# * program; if not, write to the:                                                          *\n# * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n# * MA  02111-1307, USA.                                                                    *\n# *                                                                                         *\n# * --------------------------------------------------------------------------------------- *\n# * Project:  Capwap                                                                        *\n# *                                                                                         *\n# * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *  \n# *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n# *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n# *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n# *******************************************************************************************\n\n\n\nCC = gcc-openwrt\n\n#LDFLAGS = -lssl -lcrypto -lpthread -ldl -D_REENTRANT\n#LDFLAGS = /usr/lib/libefence.a ./static/libssl.a ./static/libcrypto.a -lpthread -ldl -D_REENTRANT\nLDFLAGS = ./static/uclibc/libssl.a ./static/uclibc/libcrypto.a -lpthread -ldl -D_REENTRANT \n\nCFLAGS = -Wall -g -O0 -D_REENTRANT -I./include/ #-DCW_NO_DTLS\n\nOPENSSL_INCLUDE = #-I/usr/local/ssl/include/ #Openssl include files\n\n# Memory leak\n#LDFLAGS += ../dmalloc-5.5.0/libdmallocth.a\n#CFLAGS += -DDMALLOC\n\n# Capwap Debugging\nCFLAGS += -DCW_DEBUGGING\nCFLAGS += -DOPENSSL_NO_KRB5\n\nRM = /bin/rm -f \n\n# list of generated object files for AC. \nAC_OBJS = AC.o ACConfigFile.o ACMainLoop.o ACDiscoveryState.o ACJoinState.o ACConfigureState.o ACDataCheckState.o ACRunState.o ACProtocol_User.o ACRetransmission.o CWCommon.o CWConfigFile.o CWErrorHandling.o CWList.o CWLog.o ACMultiHomedSocket.o  ACProtocol.o CWSafeList.o CWNetwork.o CWProtocol.o CWRandom.o CWSecurity.o CWOpenSSLBio.o CWStevens.o CWThread.o CWBinding.o CWVendorPayloadsAC.o ACBinding.o ACInterface.o ACSettingsFile.o timerlib.o \n\n# list of generated object files for WTP. \nWTP_OBJS = WTP.o WTPFrameReceive.o WTPFreqStatsReceive.o WTPStatsReceive.o WTPConfigFile.o WTPProtocol.o WTPProtocol_User.o WTPDiscoveryState.o WTPJoinState.o WTPConfigureState.o WTPDataCheckState.o WTPRunState.o WTPRunStateCheck.o WTPRetransmission.o WTPSulkingState.o CWCommon.o CWConfigFile.o CWErrorHandling.o CWSafeList.o CWList.o CWLog.o CWNetwork.o CWProtocol.o CWRandom.o CWSecurity.o CWOpenSSLBio.o CWStevens.o CWThread.o CWBinding.o CWVendorPayloadsWTP.o WTPBinding.o WTPDriverInteraction.o WTPSettingsFile.o timerlib.o\n\nWUA_OBJS = WUA.o\n\nAC_SRCS = $(AC_OBJS:.o=.c) \nWTP_SRCS = $(WTP_OBJS:.o=.c)\nWUA_SRCS = $(WUA:OBJS:.o=.c)\n\nAC_DEPS := $(AC_OBJS:.o=.d)\nWTP_DEPS := $(WTP_OBJS:.o=.d)\nWUA_DEPS := $(WUA_OBJS:.o=.d)\n\n# program executables. \nAC_NAME = AC \nWTP_NAME = WTP \nWUA_NAME = WUA\n\n.PHONY: deps clean clean_libs libs\n\n# top-level rule, to compile everything. \nall: $(AC_NAME) $(WTP_NAME)\n\n$(AC_NAME): $(AC_OBJS) \n    $(CC) $(AC_OBJS) $(CC_FLAGS) $(OPENSSL_INCLUDE) $(LDFLAGS) -o $(AC_NAME) \n\n$(WTP_NAME): $(WTP_OBJS) \n    $(CC) -DWRITE_STD_OUTPUT $(WTP_OBJS) $(CC_FLAGS) $(LDFLAGS) -o $(WTP_NAME) \n\n$(WUA_NAME): $(WUA_OBJS) \n    $(CC) $(WUA_OBJS) $(CC_FLAGS)  $(LDFLAGS) -o $(WUA_NAME) \n\nclean: \n    $(RM) $(AC_NAME) $(WTP_NAME) $(WUA_NAME) $(AC_OBJS) $(WTP_OBJS) $(WUA_OBJS) $(AC_DEPS) $(WTP_DEPS) \n\nclean_deps:\n    $(AC_DEPS) $(WTP_DEPS)\n    \ndeps: $(AC_SRC) $(WTP_SRC)\n    $(CC) -MD -E $(AC_SRCS) $(CFLAGS) >/dev/null\n    $(CC) -MD -E -DWRITE_STD_OUTPUT $(WTP_SRCS) $(CFLAGS) >/dev/null\n\n-include $(AC_DEPS)\n-include $(WTP_DEPS)\n"
  },
  {
    "path": "MakefileMac",
    "content": "# *******************************************************************************************\n# * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n# *                      Universita' Campus BioMedico - Italy                               *\n# *                                                                                         *\n# * This program is free software; you can redistribute it and/or modify it under the terms *\n# * of the GNU General Public License as published by the Free Software Foundation; either  *\n# * version 2 of the License, or (at your option) any later version.                        *\n# *                                                                                         *\n# * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n# * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n# * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n# *                                                                                         *\n# * You should have received a copy of the GNU General Public License along with this       *\n# * program; if not, write to the:                                                          *\n# * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n# * MA  02111-1307, USA.                                                                    *\n# *                                                                                         * \n# * --------------------------------------------------------------------------------------- *\n# * Project:  Capwap                                                                        *\n# *                                                                                         *\n# * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *  \n# *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n# *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n# *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n# *******************************************************************************************\n\n\n\nCC = gcc \n\n#LDFLAGS = -lssl -lcrypto -lpthread -ldl -D_REENTRANT\n#LDFLAGS = /usr/lib/libefence.a ./static/libssl.a ./static/libcrypto.a -lpthread -ldl -D_REENTRANT\nLDFLAGS = /opt/local/lib/libssl.a /opt/local/lib/libcrypto.a /opt/local/lib/libz.a -lpthread -ldl -D_REENTRANT\n\nCFLAGS = -Wall -g -O0 -D_REENTRANT -I/opt/local/include/ #-DCW_NO_DTLS\n\nOPENSSL_INCLUDE = #-I/opt/local/include/ #Openssl include files\n\n# Memory leak\n#LDFLAGS += ../dmalloc-5.5.0/libdmallocth.a\n#CFLAGS += -DDMALLOC\n\n# Capwap Debugging\nCFLAGS += -DCW_DEBUGGING -DMACOSX\n\nRM = /bin/rm -f \n\n# list of generated object files for AC. \nAC_OBJS = AC.o ACConfigFile.o ACMainLoop.o ACDiscoveryState.o ACJoinState.o ACConfigureState.o ACDataCheckState.o ACRunState.o ACProtocol_User.o ACRetransmission.o CWCommon.o CWConfigFile.o CWErrorHandling.o CWList.o CWLog.o ACMultiHomedSocket.o  ACProtocol.o CWSafeList.o CWNetwork.o CWProtocol.o CWRandom.o CWSecurity.o CWOpenSSLBio.o CWStevens.o CWThread.o CWBinding.o ACBinding.o ACInterface.o ACSettingsFile.o timerlib.o\n\n# list of generated object files for WTP. \nWTP_OBJS = WTP.o WTPFrameReceive.o WTPFreqStatsReceive.o WTPStatsReceive.o WTPConfigFile.o WTPProtocol.o WTPProtocol_User.o WTPDiscoveryState.o WTPJoinState.o WTPConfigureState.o WTPDataCheckState.o WTPRunState.o WTPRunStateCheck.o WTPRetransmission.o WTPSulkingState.o CWCommon.o CWConfigFile.o CWErrorHandling.o CWSafeList.o CWList.o CWLog.o CWNetwork.o CWProtocol.o CWRandom.o CWSecurity.o CWOpenSSLBio.o CWStevens.o CWThread.o CWBinding.o WTPBinding.o WTPDriverInteraction.o WTPSettingsFile.o timerlib.o\n \nAC_SRCS = $(AC_OBJS:.o=.c) \nWTP_SRCS = $(WTP_OBJS:.o=.c)\n\nAC_DEPS := $(AC_OBJS:.o=.d)\nWTP_DEPS := $(WTP_OBJS:.o=.d)\n\n# program executables. \nAC_NAME = AC \nWTP_NAME = WTP \n\n.PHONY: deps clean clean_libs libs\n\n# top-level rule, to compile everything. \nall: $(AC_NAME) $(WTP_NAME)\n\n$(AC_NAME): $(AC_OBJS) \n    $(CC) $(AC_OBJS) $(CC_FLAGS) $(OPENSSL_INCLUDE) $(LDFLAGS) -o $(AC_NAME) \n\n$(WTP_NAME): $(WTP_OBJS) \n    $(CC) -DWRITE_STD_OUTPUT $(WTP_OBJS) $(CC_FLAGS) $(LDFLAGS) -o $(WTP_NAME) \n\nclean: \n    $(RM) $(AC_NAME) $(WTP_NAME) $(AC_OBJS) $(WTP_OBJS) $(AC_DEPS) $(WTP_DEPS)\n\nclean_deps:\n    $(AC_DEPS) $(WTP_DEPS)\n    \ndeps: $(AC_SRC) $(WTP_SRC)\n    $(CC) -MD -E $(AC_SRCS) $(CFLAGS) >/dev/null\n    $(CC) -MD -E -DWRITE_STD_OUTPUT $(WTP_SRCS) $(CFLAGS) >/dev/null\n\n-include $(AC_DEPS)\n-include $(WTP_DEPS)\n"
  },
  {
    "path": "README.md",
    "content": ""
  },
  {
    "path": "WTP.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#ifdef SOFTMAC\nCW_THREAD_RETURN_TYPE CWWTPThread_read_data_from_hostapd(void *arg);\n#endif\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveFrame(void *arg);\nCW_THREAD_RETURN_TYPE CWWTPReceiveStats(void *arg);\nCW_THREAD_RETURN_TYPE CWWTPReceiveFreqStats(void *arg);\nCW_THREAD_RETURN_TYPE gogo(void *arg);\n\nint gEnabledLog;\nint gMaxLogFileSize;\nchar gLogFileName[] = WTP_LOG_FILE_NAME;\n\n/* addresses of ACs for Discovery */\nchar **gCWACAddresses;\nint gCWACCount = 0;\n\nint gIPv4StatusDuplicate = 0;\nint gIPv6StatusDuplicate = 0;\n\nchar *gWTPLocation = NULL;\nchar *gWTPName = NULL;\nunsigned char gWTPSessionID[16];\n\n/* if not NULL, jump Discovery and use this address for Joining */\nchar *gWTPForceACAddress = NULL;\nCWAuthSecurity gWTPForceSecurity;\n\n/* UDP network socket */\nCWSocket gWTPSocket;\nCWSocket gWTPDataSocket;\n/* DTLS session vars */\nCWSecurityContext gWTPSecurityContext;\nCWSecuritySession gWTPSession;\n\n/* list used to pass frames from wireless interface to main thread */\nCWSafeList gFrameList;\n\n/* list used to pass CAPWAP packets from AC to main thread */\nCWSafeList gPacketReceiveList;\n\n/* used to synchronize access to the lists */\nCWThreadCondition gInterfaceWait;\nCWThreadMutex gInterfaceMutex;\n\n/* infos about the ACs to discover */\nCWACDescriptor *gCWACList = NULL;\n/* infos on the better AC we discovered so far */\nCWACInfoValues *gACInfoPtr = NULL;\n\n/* WTP statistics timer */\nint gWTPStatisticsTimer = CW_STATISTIC_TIMER_DEFAULT;\n\nWTPRebootStatisticsInfo gWTPRebootStatistics;\nCWWTPRadiosInfo gRadiosInfo;\n\n/* path MTU of the current session */\nint gWTPPathMTU = 0;\n\nunsigned char gWTPMACMode = CW_SPLIT_MAC;\nunsigned char gWTPTunnelMode = CW_TUNNEL_MODE_802_DOT_11_TUNNEL;\n\nint gWTPRetransmissionCount;\nCWStateTransition gWTPNextState;\n\nCWPendingRequestMessage gPendingRequestMsgs[MAX_PENDING_REQUEST_MSGS];\n\nCWBool WTPExitOnUpdateCommit = CW_FALSE;\n#define CW_SINGLE_THREAD\n\n/*\n * Receive a message, that can be fragmented. This is useful not only for the Join State\n */\nCWBool CWReceiveMessage(CWProtocolMessage * msgPtr)\n{\n\tCWList fragments = NULL;\n\tint readBytes;\n\tunsigned char buf[CW_BUFFER_SIZE];\n\tCWBool dataFlag = CW_FALSE;\n\n\tCW_REPEAT_FOREVER {\n\t\tCW_ZERO_MEMORY(buf, CW_BUFFER_SIZE);\n#ifdef CW_NO_DTLS\n\t\tchar *pkt_buffer = NULL;\n\n\t\tCWLockSafeList(gPacketReceiveList);\n\n\t\twhile (CWGetCountElementFromSafeList(gPacketReceiveList) == 0)\n\t\t\tCWWaitElementFromSafeList(gPacketReceiveList);\n\n\t\tpkt_buffer =\n\t\t    (char *)CWRemoveHeadElementFromSafeListwithDataFlag(gPacketReceiveList, &readBytes, &dataFlag);\n\n\t\tCWUnlockSafeList(gPacketReceiveList);\n\n\t\tCW_COPY_MEMORY(buf, pkt_buffer, readBytes);\n\t\tCW_FREE_OBJECT(pkt_buffer);\n#else\n\t\tif (!CWSecurityReceive(gWTPSession, buf, CW_BUFFER_SIZE, &readBytes)) {\n\t\t\treturn CW_FALSE;\n\t\t}\n#endif\n\n\t\tif (!CWProtocolParseFragment(buf, readBytes, &fragments, msgPtr, &dataFlag, NULL)) {\n\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_NEED_RESOURCE) {\t// we need at least one more fragment\n\t\t\t\tcontinue;\n\t\t\t} else {\t// error\n\t\t\t\tCWErrorCode error;\n\t\t\t\terror = CWErrorGetLastErrorCode();\n\t\t\t\tswitch (error) {\n\t\t\t\tcase CW_ERROR_SUCCESS:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Success\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_OUT_OF_MEMORY:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Out of Memory\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_WRONG_ARG:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Wrong Argument\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_INTERRUPTED:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Interrupted\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_NEED_RESOURCE:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Need Resource\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_COMUNICATING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Comunicating\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_CREATING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Creating\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_GENERAL:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: General\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_OPERATION_ABORTED:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Operation Aborted\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_SENDING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Sending\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_RECEIVING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Receiving\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_INVALID_FORMAT:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Invalid Format\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_TIME_EXPIRED:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Time Expired\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_NONE:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: None\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCWDebugLog(\"~~~~~~\");\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t} else\n\t\t\tbreak;\t// the message is fully reassembled\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWWTPSendAcknowledgedPacket(int seqNum,\n\t\t\t\t   CWList msgElemlist,\n\t\t\t\t   CWBool(assembleFunc) (CWProtocolMessage **, int *, int, int, CWList),\n\t\t\t\t   CWBool(parseFunc) (unsigned char *, int, int, void *),\n\t\t\t\t   CWBool(saveFunc) (void *), void *valuesPtr)\n{\n\n\tCWProtocolMessage *messages = NULL;\n\tCWProtocolMessage msg;\n\tint fragmentsNum = 0, i;\n\n\tstruct timespec timewait;\n\n\tint gTimeToSleep = gCWRetransmitTimer;\n\tint gMaxTimeToSleep = CW_ECHO_INTERVAL_DEFAULT / 2;\n\n\tmsg.msg = NULL;\n\n\tif (!(assembleFunc(&messages, &fragmentsNum, gWTPPathMTU, seqNum, msgElemlist))) {\n\n\t\tgoto cw_failure;\n\t}\n\n\tgWTPRetransmissionCount = 0;\n\n\twhile (gWTPRetransmissionCount < gCWMaxRetransmit) {\n\t\tCWDebugLog(\"Transmission Num:%d\", gWTPRetransmissionCount);\n\t\tfor (i = 0; i < fragmentsNum; i++) {\n#ifdef CW_NO_DTLS\n\t\t\tif (!CWNetworkSendUnsafeConnected(gWTPSocket, messages[i].msg, messages[i].offset))\n#else\n\t\t\tif (!CWSecuritySend(gWTPSession, messages[i].msg, messages[i].offset))\n#endif\n\t\t\t{\n\t\t\t\tCWDebugLog(\"Failure sending Request\");\n\t\t\t\tgoto cw_failure;\n\t\t\t}\n\t\t}\n\n\t\ttimewait.tv_sec = time(0) + gTimeToSleep;\n\t\ttimewait.tv_nsec = 0;\n\n\t\tCW_REPEAT_FOREVER {\n\t\t\tCWThreadMutexLock(&gInterfaceMutex);\n\n\t\t\tif (CWGetCountElementFromSafeList(gPacketReceiveList) > 0)\n\t\t\t\tCWErrorRaise(CW_ERROR_SUCCESS, NULL);\n\t\t\telse {\n\t\t\t\tif (CWErr(CWWaitThreadConditionTimeout(&gInterfaceWait, &gInterfaceMutex, &timewait)))\n\t\t\t\t\tCWErrorRaise(CW_ERROR_SUCCESS, NULL);\n\t\t\t}\n\n\t\t\tCWThreadMutexUnlock(&gInterfaceMutex);\n\n\t\t\tswitch (CWErrorGetLastErrorCode()) {\n\n\t\t\tcase CW_ERROR_TIME_EXPIRED:{\n\t\t\t\t\tgWTPRetransmissionCount++;\n\t\t\t\t\tgoto cw_continue_external_loop;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase CW_ERROR_SUCCESS:{\n\t\t\t\t\t/* there's something to read */\n\t\t\t\t\tif (!(CWReceiveMessage(&msg))) {\n\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t\t\t\t\tCWDebugLog(\"Failure Receiving Response\");\n\t\t\t\t\t\tgoto cw_failure;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!(parseFunc(msg.msg, msg.offset, seqNum, valuesPtr))) {\n\t\t\t\t\t\tif (CWErrorGetLastErrorCode() != CW_ERROR_INVALID_FORMAT) {\n\n\t\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t\t\t\t\t\tCWDebugLog(\"Failure Parsing Response\");\n\t\t\t\t\t\t\tgoto cw_failure;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tgWTPRetransmissionCount++;\n\t\t\t\t\t\t\t\tgoto cw_continue_external_loop;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ((saveFunc(valuesPtr))) {\n\n\t\t\t\t\t\tgoto cw_success;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (CWErrorGetLastErrorCode() != CW_ERROR_INVALID_FORMAT) {\n\t\t\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t\t\t\t\t\tCWDebugLog(\"Failure Saving Response\");\n\t\t\t\t\t\t\tgoto cw_failure;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase CW_ERROR_INTERRUPTED:{\n\t\t\t\t\tgWTPRetransmissionCount++;\n\t\t\t\t\tgoto cw_continue_external_loop;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tdefault:{\n\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\tCWDebugLog(\"Failure\");\n\t\t\t\t\tgoto cw_failure;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n cw_continue_external_loop:\n\t\tCWDebugLog(\"Retransmission time is over\");\n\n\t\tgTimeToSleep <<= 1;\n\t\tif (gTimeToSleep > gMaxTimeToSleep)\n\t\t\tgTimeToSleep = gMaxTimeToSleep;\n\t}\n\n\t/* too many retransmissions */\n\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"Peer Dead\");\n\n cw_success:\n\tfor (i = 0; i < fragmentsNum; i++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t}\n\n\tCW_FREE_OBJECT(messages);\n\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\n\treturn CW_TRUE;\n\n cw_failure:\n\tif (messages != NULL) {\n\t\tfor (i = 0; i < fragmentsNum; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(messages);\n\t}\n\tCWDebugLog(\"Failure\");\n\treturn CW_FALSE;\n}\n\nvoid usage(void)\n{\n}\n\nint main(int argc, char * const argv[])\n{\n\tint run_daemon = 1;\n\tint c;\n\n#ifdef CW_DEBUGGING\n\tconst struct rlimit rlim = {\n\t\t.rlim_cur = RLIM_INFINITY,\n\t\t.rlim_max = RLIM_INFINITY\n\t};\n\n\t/* unlimited size for cores */\n\tsetrlimit(RLIMIT_CORE, &rlim);\n#endif\n\n\twhile (-1 != (c = getopt(argc, argv, \"hf\"))) {\n\t\tswitch(c) {\n\t\tcase 'h':\n\t\t\tusage();\n\t\t\texit(1);\n\t\t\tbreak;\n\n\t\tcase 'f':\n\t\t\trun_daemon = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tusage();\n\t\t\texit(1);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Daemon Mode */\n\tif (run_daemon)\n\t\tif (daemon(1, 0) != 0) {\n\t\t\tfprintf(stderr, \"daemon failed: %s\\n\", strerror(errno));\n\t\t\texit(1);\n\n\t\t}\n\n\tCWLogInitFile(WTP_LOG_FILE_NAME);\n        fprintf(stderr, \"log init done\\n\");\n\n#ifndef CW_SINGLE_THREAD\n\tCWDebugLog(\"Use Threads\");\n#else\n\tCWDebugLog(\"Don't Use Threads\");\n#endif\n\tfprintf(stderr, \"log init done\\n\");\n\tCWErrorHandlingInitLib();\n\tif (!CWParseSettingsFile()) {\n\t\tCWLog(\"Can't start WTP\");\n\t\texit(1);\n\t}\n\n\t/* Capwap receive packets list */\n\tif (!CWErr(CWCreateSafeList(&gPacketReceiveList))) {\n\t\tCWLog(\"Can't start WTP\");\n\t\texit(1);\n\t}\n\n\t/* Capwap receive frame list */\n\tif (!CWErr(CWCreateSafeList(&gFrameList))) {\n\t\tCWLog(\"Can't start WTP\");\n\t\texit(1);\n\t}\n\n\tCWCreateThreadMutex(&gInterfaceMutex);\n\tCWSetMutexSafeList(gPacketReceiveList, &gInterfaceMutex);\n\tCWSetMutexSafeList(gFrameList, &gInterfaceMutex);\n\tCWCreateThreadCondition(&gInterfaceWait);\n\tCWSetConditionSafeList(gPacketReceiveList, &gInterfaceWait);\n\tCWSetConditionSafeList(gFrameList, &gInterfaceWait);\n\n\tCWLog(\"Starting WTP...\");\n\n\tCWRandomInitLib();\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n\tif (timer_init() == 0) {\n\t\tCWLog(\"Can't init timer module\");\n\t\texit(1);\n\t}\n\n#ifdef CW_NO_DTLS\n\tif (!CWErr(CWWTPLoadConfiguration())) {\n#else\n\tif (!CWErr(CWSecurityInitLib()) || !CWErr(CWWTPLoadConfiguration())) {\n#endif\n\t\tCWLog(\"Can't start WTP\");\n\t\texit(1);\n\t}\n\n\tCWDebugLog(\"Init WTP Radio Info\");\n\tif (!CWWTPInitConfiguration()) {\n\t\tCWLog(\"Error Init Configuration\");\n\t\texit(1);\n\t}\n#ifdef SOFTMAC\n\tCWThread thread_ipc_with_wtp_hostapd;\n\tif (!CWErr(CWCreateThread(&thread_ipc_with_wtp_hostapd, CWWTPThread_read_data_from_hostapd, NULL))) {\n\t\tCWLog(\"Error starting Thread that receive command and 802.11 frame from hostapd (WTP side)\");\n\t\texit(1);\n\t}\n#endif\n\n\tCWThread thread_receiveFrame;\n\tif (!CWErr(CWCreateThread(&thread_receiveFrame, CWWTPReceiveFrame, NULL))) {\n\t\tCWLog(\"Error starting Thread that receive binding frame\");\n\t\texit(1);\n\t}\n\n\tCWThread thread_receiveStats;\n\tif (!CWErr(CWCreateThread(&thread_receiveStats, CWWTPReceiveStats, NULL))) {\n\t\tCWLog(\"Error starting Thread that receive stats on monitoring interface\");\n\t\texit(1);\n\t}\n\n\t/****************************************\n\t * 2009 Update:                         *\n\t *              Spawn Frequency Stats   *\n\t *              Receiver Thread         *\n\t ****************************************/\n\n\tCWThread thread_receiveFreqStats;\n\tif (!CWErr(CWCreateThread(&thread_receiveFreqStats, CWWTPReceiveFreqStats, NULL))) {\n\t\tCWLog(\"Error starting Thread that receive frequency stats on monitoring interface\");\n\t\texit(1);\n\t}\n\n\t/* if AC address is given jump Discovery and use this address for Joining */\n\tif (gWTPForceACAddress != NULL)\n\t\tgWTPNextState = CW_ENTER_JOIN;\n\n\t/* Setting hostapd default MAC char for checking in join state */\n\tgRADIO_MAC[0] = 0xAA;\n\n\t/* start CAPWAP state machine */\n\tCW_REPEAT_FOREVER {\n                CWDebugLog(\"nextState is %d\", gWTPNextState);\n\t\tswitch (gWTPNextState) {\n\t\tcase CW_ENTER_DISCOVERY:\n\t\t\tgWTPNextState = CWWTPEnterDiscovery();\n\t\t\tbreak;\n\t\tcase CW_ENTER_SULKING:\n\t\t\tgWTPNextState = CWWTPEnterSulking();\n\t\t\tbreak;\n\t\tcase CW_ENTER_JOIN:\n\t\t\tgWTPNextState = CWWTPEnterJoin();\n\t\t\tbreak;\n\t\tcase CW_ENTER_CONFIGURE:\n\t\t\tgWTPNextState = CWWTPEnterConfigure();\n\t\t\tbreak;\n\t\tcase CW_ENTER_DATA_CHECK:\n\t\t\tgWTPNextState = CWWTPEnterDataCheck();\n\t\t\tbreak;\n\t\tcase CW_ENTER_RUN:\n\t\t\tgWTPNextState = CWWTPEnterRun();\n\t\t\tbreak;\n\t\tcase CW_ENTER_RESET:\n\t\t\t/*\n\t\t\t * CWStopHeartbeatTimer();\n\t\t\t * CWStopNeighborDeadTimer();\n\t\t\t * CWNetworkCloseSocket(gWTPSocket);\n\t\t\t * CWSecurityDestroySession(gWTPSession);\n\t\t\t * CWSecurityDestroyContext(gWTPSecurityContext);\n\t\t\t * gWTPSecurityContext = NULL;\n\t\t\t * gWTPSession = NULL;\n\t\t\t */\n\t\t\tif (gWTPForceACAddress != NULL)\n\t\t\t\tgWTPNextState = CW_ENTER_JOIN;\n\t\t\telse\n\t\t\t\tgWTPNextState = CW_ENTER_DISCOVERY;\n\t\t\tbreak;\n\t\tcase CW_QUIT:\n\t\t\tCWWTPDestroy();\n\t\t\tCWLogCloseFile();\n\t\t\treturn 0;\n\t\t}\n\t}\n}\n\nunsigned int CWGetSeqNum()\n{\n\tstatic unsigned int seqNum = 0;\n\n\tif (seqNum == CW_MAX_SEQ_NUM)\n\t\tseqNum = 0;\n\telse\n\t\tseqNum++;\n\treturn seqNum;\n}\n\nint CWGetFragmentID()\n{\n\tstatic int fragID = 0;\n\treturn fragID++;\n}\n\n/*\n * Parses config file and inits WTP configuration.\n */\nCWBool CWWTPLoadConfiguration()\n{\n\tint i;\n\n\tCWLog(\"WTP Loads Configuration\");\n\n\t/* get saved preferences */\n\tif (!CWErr(CWParseConfigFile())) {\n\t\tCWLog(\"Can't Read Config File\");\n\t\texit(1);\n\t}\n\n\tif (gCWACCount == 0)\n\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, \"No AC Configured\");\n\n\tCW_CREATE_ARRAY_ERR(gCWACList, gCWACCount, CWACDescriptor, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < gCWACCount; i++) {\n\n\t\tCWDebugLog(\"Init Configuration for AC at %s\", gCWACAddresses[i]);\n\t\tCW_CREATE_STRING_FROM_STRING_ERR(gCWACList[i].address, gCWACAddresses[i],\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\n\tCW_FREE_OBJECTS_ARRAY(gCWACAddresses, gCWACCount);\n\treturn CW_TRUE;\n}\n\nvoid CWWTPDestroy()\n{\n\tint i;\n\n\tCWLog(\"Destroy WTP\");\n\n\tfor (i = 0; i < gCWACCount; i++) {\n\t\tCW_FREE_OBJECT(gCWACList[i].address);\n\t}\n\n\ttimer_destroy();\n\n\tCW_FREE_OBJECT(gCWACList);\n\tCW_FREE_OBJECT(gRadiosInfo.radiosInfo);\n}\n\nCWBool CWWTPInitConfiguration()\n{\n\tCWDebugLog(\"CWWTPInitConfiguration\");\n\tint i;\n\n\t//Generate 128-bit Session ID,\n\tinitWTPSessionID(&gWTPSessionID[0]);\n\n\tCWWTPResetRebootStatistics(&gWTPRebootStatistics);\n\n\tgRadiosInfo.radioCount = CWWTPGetMaxRadios();\n\n\tCW_CREATE_ARRAY_ERR(gRadiosInfo.radiosInfo, gRadiosInfo.radioCount, CWWTPRadioInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tgRadiosInfo.radiosInfo[0].radioID = 0;\n\n\t/* gRadiosInfo.radiosInfo[0].numEntries = 0; */\n\tgRadiosInfo.radiosInfo[0].decryptErrorMACAddressList = NULL;\n\tgRadiosInfo.radiosInfo[0].reportInterval = CW_REPORT_INTERVAL_DEFAULT;\n\tgRadiosInfo.radiosInfo[0].adminState = ENABLED;\n\tgRadiosInfo.radiosInfo[0].adminCause = AD_NORMAL;\n\tgRadiosInfo.radiosInfo[0].operationalState = ENABLED;\n\tgRadiosInfo.radiosInfo[0].operationalCause = OP_NORMAL;\n\tgRadiosInfo.radiosInfo[0].TxQueueLevel = 0;\n\tgRadiosInfo.radiosInfo[0].wirelessLinkFramesPerSec = 0;\n\n\tCWWTPResetRadioStatistics(&(gRadiosInfo.radiosInfo[0].statistics));\n\n\tif (!CWWTPInitBinding(0)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tfor (i = 1; i < gRadiosInfo.radioCount; i++) {\n\t\tgRadiosInfo.radiosInfo[i].radioID = i;\n\t\t/* gRadiosInfo.radiosInfo[i].numEntries = 0; */\n\t\tgRadiosInfo.radiosInfo[i].decryptErrorMACAddressList = NULL;\n\t\tgRadiosInfo.radiosInfo[i].reportInterval = CW_REPORT_INTERVAL_DEFAULT;\n\t\t/* Default value for CAPWA� */\n\t\tgRadiosInfo.radiosInfo[i].adminState = ENABLED;\n\t\tgRadiosInfo.radiosInfo[i].adminCause = AD_NORMAL;\n\t\tgRadiosInfo.radiosInfo[i].operationalState = DISABLED;\n\t\tgRadiosInfo.radiosInfo[i].operationalCause = OP_NORMAL;\n\t\tgRadiosInfo.radiosInfo[i].TxQueueLevel = 0;\n\t\tgRadiosInfo.radiosInfo[i].wirelessLinkFramesPerSec = 0;\n\t\tCWWTPResetRadioStatistics(&(gRadiosInfo.radiosInfo[i].statistics));\n\t\tif (!CWWTPInitBinding(i)) {\n\t\t\treturn CW_FALSE;\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "WTPBcmDriverInteraction.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n#include \"WTPBcmDriverInteraction.h\"\n\nstatic char interface[16] = \"wl0\";\nstatic char wlbuf[WLC_IOCTL_MAXLEN];\n#define BUFSIZE 8192\n\n/*prototipi da includere in CWWTP.h*/\nint set_rts_threshold(int value);\nint get_rts_threshold(int *value);\n\nint set_frag_threshold(int value);\nint get_frag_threshold(int *value);\n\nint set_maxassoc(int value);\nint get_maxassoc(int *value);\n\n/*--------------------------- RTS/CTS Threshold ---------------------------*/\nint set_rts_threshold(int value)\n{\n\tchar *iov_type;\n\n\tiov_type = malloc(20 * sizeof(char));\n\tstrcpy(iov_type, \"rtsthresh\");\n\n\tif (wl_iovar_setint(interface, iov_type, value) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nRTS/CTS threshold impostato a: %d\\n\", value);\n\treturn 1;\n}\n\nint get_rts_threshold(int *value)\n{\n\tchar *iov_type;\n\n\tiov_type = malloc(20 * sizeof(char));\n\tstrcpy(iov_type, \"rtsthresh\");\n\n\tif (wl_iovar_getint(interface, iov_type, value) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nRTS/CTS threshold: %d\\n\", *value);\n\treturn 1;\n}\n\n/*--------------------------- Fragmentation Threshold ---------------------------*/\nint set_frag_threshold(int value)\n{\n\tchar *iov_type;\n\n\tiov_type = malloc(20 * sizeof(char));\n\tstrcpy(iov_type, \"fragthresh\");\n\n\tif (wl_iovar_setint(interface, iov_type, value) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nFragmentation threshold impostato a: %d\\n\", value);\n\treturn 1;\n}\n\nint get_frag_threshold(int *value)\n{\n\tchar *iov_type;\n\n\tiov_type = malloc(20 * sizeof(char));\n\tstrcpy(iov_type, \"fragthresh\");\n\n\tif (wl_iovar_getint(interface, iov_type, value) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nFragmentation threshold: %d\\n\", *value);\n\treturn 1;\n}\n\n/*--------------------------- Max. number of associated clients ---------------------------*/\nint set_maxassoc(int value)\n{\n\tchar *iov_type;\n\n\tiov_type = malloc(20 * sizeof(char));\n\tstrcpy(iov_type, \"maxassoc\");\n\n\tif (wl_iovar_setint(interface, iov_type, value) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nMax. number of associated clients impostato a: %d\\n\", value);\n\treturn 1;\n}\n\nint get_maxassoc(int *value)\n{\n\tchar *iov_type;\n\n\tiov_type = malloc(20 * sizeof(char));\n\tstrcpy(iov_type, \"maxassoc\");\n\n\tif (wl_iovar_getint(interface, iov_type, value) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nMax. number of associated clients: %d\\n\", *value);\n\treturn 1;\n}\n\n/*---------- WME Extensions: cwmin,cwmax,aifsn for BE,BK,VI,VO queues ---------------------*/\n/*the Broadcom's driver doesn't support GET command for wme.*/\n\n/*set CWMIN*/\nint set_wme_cwmin(int class, int value)\n{\n\tedcf_acparam_t params[AC_COUNT];\n\tchar *buf = wlbuf;\n\tchar *type;\n\n\ttype = malloc(20 * sizeof(char));\n\tstrcpy(type, \"wme_ac_ap\");\n\n\tmemset(params, 0, sizeof(params));\n\twl_iovar_get(interface, type, params, sizeof(params));\n\n\tstrcpy(buf, type);\n\tbuf += strlen(buf) + 1;\n\n\tparams[class].ECW = (params[class].ECW & ~(0xf)) | (value & 0xf);\n\tmemcpy(buf, &params[class], sizeof(edcf_acparam_t));\n\n\tif (wl_ioctl(interface, WLC_SET_VAR, wlbuf, BUFSIZE) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nCWMIN impostato a: %d\\n\", value);\n\treturn 1;\n}\n\n/*set CWMAX*/\nint set_wme_cwmax(int class, int value)\n{\n\tedcf_acparam_t params[AC_COUNT];\n\tchar *buf = wlbuf;\n\tchar *type;\n\n\ttype = malloc(20 * sizeof(char));\n\tstrcpy(type, \"wme_ac_ap\");\n\n\tmemset(params, 0, sizeof(params));\n\twl_iovar_get(interface, type, params, sizeof(params));\n\n\tstrcpy(buf, type);\n\tbuf += strlen(buf) + 1;\n\n\tparams[class].ECW = (params[class].ECW & ~(0xf << 4)) | ((value & 0xf) << 4);\n\tmemcpy(buf, &params[class], sizeof(edcf_acparam_t));\n\n\tif (wl_ioctl(interface, WLC_SET_VAR, wlbuf, BUFSIZE) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nCWMAX impostato a: %d\\n\", value);\n\treturn 1;\n}\n\n/*set AIFSN*/\nint set_wme_aifsn(int class, int value)\n{\n\tedcf_acparam_t params[AC_COUNT];\n\tchar *buf = wlbuf;\n\tchar *type;\n\n\ttype = malloc(20 * sizeof(char));\n\tstrcpy(type, \"wme_ac_ap\");\n\n\tmemset(params, 0, sizeof(params));\n\twl_iovar_get(interface, type, params, sizeof(params));\n\n\tstrcpy(buf, type);\n\tbuf += strlen(buf) + 1;\n\n\tparams[class].ACI = (params[class].ACI & ~(0xf)) | (value & 0xf);\n\tmemcpy(buf, &params[class], sizeof(edcf_acparam_t));\n\n\tif (wl_ioctl(interface, WLC_SET_VAR, wlbuf, BUFSIZE) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nAIFSN impostato a: %d\\n\", value);\n\treturn 1;\n}\n\n/*@@@@@@@@ ioctl driver interaction's functions @@@@@@@@@@@@@*/\n\nint wl_ioctl(char *name, int cmd, void *buf, int len)\n{\n\tstruct ifreq ifr;\n\twl_ioctl_t ioc;\n\tint ret = 0;\n\tint s;\n\n\t/* open socket to kernel */\n\tif ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {\n\t\tperror(\"socket\");\n\t\treturn errno;\n\t}\n\n\t/* do it */\n\tioc.cmd = cmd;\n\tioc.buf = buf;\n\tioc.len = len;\n\tstrncpy(ifr.ifr_name, name, IFNAMSIZ);\n\tifr.ifr_data = (caddr_t) & ioc;\n\tif ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0) {\n\t\tperror(\"ioctl error\");\n\t\tclose(s);\n\t\treturn -1;\n\t}\n\n\t/* cleanup */\n\tclose(s);\n\treturn ret;\n}\n\nstatic int wl_iovar_getbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)\n{\n\tint err;\n\tuint namelen;\n\tuint iolen;\n\n\tnamelen = strlen(iovar) + 1;\t/* length of iovar name plus null */\n\tiolen = namelen + paramlen;\n\n\t/* check for overflow */\n\tif (iolen > buflen)\n\t\treturn (BCME_BUFTOOSHORT);\n\n\tmemcpy(bufptr, iovar, namelen);\t/* copy iovar name including null */\n\tmemcpy((int8 *) bufptr + namelen, param, paramlen);\n\n\terr = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);\n\n\treturn (err);\n}\n\nstatic int wl_iovar_setbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)\n{\n\tuint namelen;\n\tuint iolen;\n\n\tnamelen = strlen(iovar) + 1;\t/* length of iovar name plus null */\n\tiolen = namelen + paramlen;\n\n\t/* check for overflow */\n\tif (iolen > buflen)\n\t\treturn (BCME_BUFTOOSHORT);\n\n\tmemcpy(bufptr, iovar, namelen);\t/* copy iovar name including null */\n\tmemcpy((int8 *) bufptr + namelen, param, paramlen);\n\n\treturn wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);\n}\n\nint wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)\n{\n\tchar smbuf[WLC_IOCTL_SMLEN];\n\n\treturn wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf));\n}\n\nint wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)\n{\n\tchar smbuf[WLC_IOCTL_SMLEN];\n\tint ret;\n\n\t/* use the return buffer if it is bigger than what we have on the stack */\n\tif (buflen > sizeof(smbuf)) {\n\t\tret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);\n\t} else {\n\t\tret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf));\n\t\tif (ret == 0)\n\t\t\tmemcpy(bufptr, smbuf, buflen);\n\t}\n\n\treturn ret;\n}\n"
  },
  {
    "path": "WTPBcmDriverInteraction.h",
    "content": "#define __CAPWAP_WTPBroadcomDriverInteraction_HEADER__\n\n/* check this magic number */\n#define WLC_IOCTL_MAGIC     0x14e46c77\n\n/* bump this number if you change the ioctl interface */\n#define WLC_IOCTL_VERSION   1\n\n#define WLC_IOCTL_MAXLEN    8192\t/* max length ioctl buffer required */\n#define WLC_IOCTL_SMLEN     256\t/* \"small\" length ioctl buffer required */\n\n/* common ioctl definitions */\n#define WLC_GET_MAGIC               0\n#define WLC_GET_VERSION             1\n#define WLC_UP                  2\n#define WLC_DOWN                3\n#define WLC_DUMP                6\n#define WLC_GET_MSGLEVEL            7\n#define WLC_SET_MSGLEVEL            8\n#define WLC_GET_PROMISC             9\n#define WLC_SET_PROMISC             10\n#define WLC_GET_RATE                12\n\t\t\t\t\t  /* #define WLC_SET_RATE             13 *//* no longer supported */\n#define WLC_GET_INSTANCE            14\n\t\t\t\t\t  /* #define WLC_GET_FRAG             15 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_FRAG             16 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_GET_RTS              17 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_RTS              18 *//* no longer supported */\n#define WLC_GET_INFRA               19\n#define WLC_SET_INFRA               20\n#define WLC_GET_AUTH                21\n#define WLC_SET_AUTH                22\n#define WLC_GET_BSSID               23\n#define WLC_SET_BSSID               24\n#define WLC_GET_SSID                25\n#define WLC_SET_SSID                26\n#define WLC_RESTART             27\n#define WLC_GET_CHANNEL             29\n#define WLC_SET_CHANNEL             30\n#define WLC_GET_SRL             31\n#define WLC_SET_SRL             32\n#define WLC_GET_LRL             33\n#define WLC_SET_LRL             34\n#define WLC_GET_PLCPHDR             35\n#define WLC_SET_PLCPHDR             36\n#define WLC_GET_RADIO               37\n#define WLC_SET_RADIO               38\n#define WLC_GET_PHYTYPE             39\n\t\t\t\t\t  /* #define WLC_GET_WEP              42 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_WEP              43 *//* no longer supported */\n#define WLC_GET_KEY             44\n#define WLC_SET_KEY             45\n#define WLC_GET_REGULATORY          46\n#define WLC_SET_REGULATORY          47\n#define WLC_GET_PASSIVE             48\n#define WLC_SET_PASSIVE             49\n#define WLC_SCAN                50\n#define WLC_SCAN_RESULTS            51\n#define WLC_DISASSOC                52\n#define WLC_REASSOC             53\n#define WLC_GET_ROAM_TRIGGER            54\n#define WLC_SET_ROAM_TRIGGER            55\n#define WLC_GET_TXANT               61\n#define WLC_SET_TXANT               62\n#define WLC_GET_ANTDIV              63\n#define WLC_SET_ANTDIV              64\n\t\t\t\t\t  /* #define WLC_GET_TXPWR            65 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_TXPWR            66 *//* no longer supported */\n#define WLC_GET_CLOSED              67\n#define WLC_SET_CLOSED              68\n#define WLC_GET_MACLIST             69\n#define WLC_SET_MACLIST             70\n#define WLC_GET_RATESET             71\n#define WLC_SET_RATESET             72\n#define WLC_GET_LOCALE              73\n#define WLC_LONGTRAIN               74\n#define WLC_GET_BCNPRD              75\n#define WLC_SET_BCNPRD              76\n#define WLC_GET_DTIMPRD             77\n#define WLC_SET_DTIMPRD             78\n#define WLC_GET_SROM                79\n#define WLC_SET_SROM                80\n#define WLC_GET_WEP_RESTRICT            81\n#define WLC_SET_WEP_RESTRICT            82\n#define WLC_GET_COUNTRY             83\n#define WLC_SET_COUNTRY             84\n#define WLC_GET_PM              85\n#define WLC_SET_PM              86\n#define WLC_GET_WAKE                87\n#define WLC_SET_WAKE                88\n#define WLC_GET_D11CNTS             89\n#define WLC_GET_FORCELINK           90\t/* ndis only */\n#define WLC_SET_FORCELINK           91\t/* ndis only */\n#define WLC_FREQ_ACCURACY           92\n#define WLC_CARRIER_SUPPRESS            93\n#define WLC_GET_PHYREG              94\n#define WLC_SET_PHYREG              95\n#define WLC_GET_RADIOREG            96\n#define WLC_SET_RADIOREG            97\n#define WLC_GET_REVINFO             98\n#define WLC_GET_UCANTDIV            99\n#define WLC_SET_UCANTDIV            100\n#define WLC_R_REG               101\n#define WLC_W_REG               102\n#define WLC_DIAG_LOOPBACK           103\n#define WLC_RESET_D11CNTS           104\n#define WLC_GET_MACMODE             105\n#define WLC_SET_MACMODE             106\n#define WLC_GET_MONITOR             107\n#define WLC_SET_MONITOR             108\n#define WLC_GET_GMODE               109\n#define WLC_SET_GMODE               110\n#define WLC_GET_LEGACY_ERP          111\n#define WLC_SET_LEGACY_ERP          112\n#define WLC_GET_RX_ANT              113\n#define WLC_GET_CURR_RATESET            114\t/* current rateset */\n#define WLC_GET_SCANSUPPRESS            115\n#define WLC_SET_SCANSUPPRESS            116\n#define WLC_GET_AP              117\n#define WLC_SET_AP              118\n#define WLC_GET_EAP_RESTRICT            119\n#define WLC_SET_EAP_RESTRICT            120\n#define WLC_SCB_AUTHORIZE           121\n#define WLC_SCB_DEAUTHORIZE         122\n#define WLC_GET_WDSLIST             123\n#define WLC_SET_WDSLIST             124\n#define WLC_GET_ATIM                125\n#define WLC_SET_ATIM                126\n#define WLC_GET_RSSI                127\n#define WLC_GET_PHYANTDIV           128\n#define WLC_SET_PHYANTDIV           129\n#define WLC_AP_RX_ONLY              130\n#define WLC_GET_TX_PATH_PWR         131\n#define WLC_SET_TX_PATH_PWR         132\n#define WLC_GET_WSEC                133\n#define WLC_SET_WSEC                134\n#define WLC_GET_PHY_NOISE           135\n#define WLC_GET_BSS_INFO            136\n#define WLC_GET_PKTCNTS             137\n#define WLC_GET_LAZYWDS             138\n#define WLC_SET_LAZYWDS             139\n#define WLC_GET_BANDLIST            140\n#define WLC_GET_BAND                141\n#define WLC_SET_BAND                142\n#define WLC_SCB_DEAUTHENTICATE          143\n#define WLC_GET_SHORTSLOT           144\n#define WLC_GET_SHORTSLOT_OVERRIDE      145\n#define WLC_SET_SHORTSLOT_OVERRIDE      146\n#define WLC_GET_SHORTSLOT_RESTRICT      147\n#define WLC_SET_SHORTSLOT_RESTRICT      148\n#define WLC_GET_GMODE_PROTECTION        149\n#define WLC_GET_GMODE_PROTECTION_OVERRIDE   150\n#define WLC_SET_GMODE_PROTECTION_OVERRIDE   151\n#define WLC_UPGRADE             152\n\t\t\t\t\t   /* #define WLC_GET_MRATE            153 *//* no longer supported */\n\t\t\t\t\t   /* #define WLC_SET_MRATE            154 *//* no longer supported */\n#define WLC_GET_ASSOCLIST           159\n#define WLC_GET_CLK             160\n#define WLC_SET_CLK             161\n#define WLC_GET_UP              162\n#define WLC_OUT                 163\n#define WLC_GET_WPA_AUTH            164\n#define WLC_SET_WPA_AUTH            165\n#define WLC_GET_PROTECTION_CONTROL      178\n#define WLC_SET_PROTECTION_CONTROL      179\n#define WLC_GET_PHYLIST             180\n#define WLC_GET_KEY_SEQ             183\n\t\t\t\t\t\t   /* #define WLC_GET_GMODE_PROTECTION_CTS     198 *//* no longer supported */\n\t\t\t\t\t\t   /* #define WLC_SET_GMODE_PROTECTION_CTS     199 *//* no longer supported */\n#define WLC_GET_PIOMODE             203\n#define WLC_SET_PIOMODE             204\n#define WLC_SET_LED             209\n#define WLC_GET_LED             210\n#define WLC_GET_CHANNEL_SEL         215\n#define WLC_START_CHANNEL_SEL           216\n#define WLC_GET_VALID_CHANNELS          217\n#define WLC_GET_FAKEFRAG            218\n#define WLC_SET_FAKEFRAG            219\n#define WLC_GET_WET             230\n#define WLC_SET_WET             231\n#define WLC_GET_KEY_PRIMARY         235\n#define WLC_SET_KEY_PRIMARY         236\n#define WLC_GET_RADAR               242\n#define WLC_SET_RADAR               243\n#define WLC_SET_SPECT_MANAGMENT         244\n#define WLC_GET_SPECT_MANAGMENT         245\n#define WLC_WDS_GET_REMOTE_HWADDR       246\t/* handled in wl_linux.c/wl_vx.c */\n#define WLC_SET_CS_SCAN_TIMER           248\n#define WLC_GET_CS_SCAN_TIMER           249\n#define WLC_SEND_PWR_CONSTRAINT         254\n#define WLC_CURRENT_PWR             256\n#define WLC_GET_CHANNELS_IN_COUNTRY     260\n#define WLC_GET_COUNTRY_LIST            261\n#define WLC_GET_VAR             262\t/* get value of named variable */\n#define WLC_SET_VAR             263\t/* set named variable to value */\n#define WLC_NVRAM_GET               264\t/* deprecated */\n#define WLC_NVRAM_SET               265\n#define WLC_SET_WSEC_PMK            268\n#define WLC_GET_AUTH_MODE           269\n#define WLC_SET_AUTH_MODE           270\n#define WLC_NDCONFIG_ITEM           273\t/* currently handled in wl_oid.c */\n#define WLC_NVOTPW              274\n#define WLC_OTPW                275\n#define WLC_SET_LOCALE              278\n#define WLC_LAST                279\t/* do not change - use get_var/set_var */\n\n/* ** driver/apps-shared section ** */\n\n#define BCME_STRLEN         64\t/* Max string length for BCM errors */\n#define VALID_BCMERROR(e)  ((e <= 0) && (e >= BCME_LAST))\n\n/*\n * error codes could be added but the defined ones shouldn't be changed/deleted\n * these error codes are exposed to the user code\n * when ever a new error code is added to this list\n * please update errorstring table with the related error string and\n * update osl files with os specific errorcode map\n*/\n\n#define BCME_OK             0\t/* Success */\n#define BCME_ERROR          -1\t/* Error generic */\n#define BCME_BADARG         -2\t/* Bad Argument */\n#define BCME_BADOPTION          -3\t/* Bad option */\n#define BCME_NOTUP          -4\t/* Not up */\n#define BCME_NOTDOWN            -5\t/* Not down */\n#define BCME_NOTAP          -6\t/* Not AP */\n#define BCME_NOTSTA         -7\t/* Not STA  */\n#define BCME_BADKEYIDX          -8\t/* BAD Key Index */\n#define BCME_RADIOOFF           -9\t/* Radio Off */\n#define BCME_NOTBANDLOCKED      -10\t/* Not  band locked */\n#define BCME_NOCLK          -11\t/* No Clock */\n#define BCME_BADRATESET         -12\t/* BAD Rate valueset */\n#define BCME_BADBAND            -13\t/* BAD Band */\n#define BCME_BUFTOOSHORT        -14\t/* Buffer too short */\n#define BCME_BUFTOOLONG         -15\t/* Buffer too long */\n#define BCME_BUSY           -16\t/* Busy */\n#define BCME_NOTASSOCIATED      -17\t/* Not Associated */\n#define BCME_BADSSIDLEN         -18\t/* Bad SSID len */\n#define BCME_OUTOFRANGECHAN     -19\t/* Out of Range Channel */\n#define BCME_BADCHAN            -20\t/* Bad Channel */\n#define BCME_BADADDR            -21\t/* Bad Address */\n#define BCME_NORESOURCE         -22\t/* Not Enough Resources */\n#define BCME_UNSUPPORTED        -23\t/* Unsupported */\n#define BCME_BADLEN         -24\t/* Bad length */\n#define BCME_NOTREADY           -25\t/* Not Ready */\n#define BCME_EPERM          -26\t/* Not Permitted */\n#define BCME_NOMEM          -27\t/* No Memory */\n#define BCME_ASSOCIATED         -28\t/* Associated */\n#define BCME_RANGE          -29\t/* Not In Range */\n#define BCME_NOTFOUND           -30\t/* Not Found */\n#define BCME_WME_NOT_ENABLED        -31\t/* WME Not Enabled */\n#define BCME_TSPEC_NOTFOUND     -32\t/* TSPEC Not Found */\n#define BCME_ACM_NOTSUPPORTED       -33\t/* ACM Not Supported */\n#define BCME_NOT_WME_ASSOCIATION    -34\t/* Not WME Association */\n#define BCME_SDIO_ERROR         -35\t/* SDIO Bus Error */\n#define BCME_DONGLE_DOWN        -36\t/* Dongle Not Accessible */\n#define BCME_LAST           BCME_DONGLE_DOWN\n\n/* These are collection of BCME Error strings */\n#define BCMERRSTRINGTABLE {     \\\n    \"OK\",               \\\n    \"Undefined error\",      \\\n    \"Bad Argument\",         \\\n    \"Bad Option\",           \\\n    \"Not up\",           \\\n    \"Not down\",         \\\n    \"Not AP\",           \\\n    \"Not STA\",          \\\n    \"Bad Key Index\",        \\\n    \"Radio Off\",            \\\n    \"Not band locked\",      \\\n    \"No clock\",         \\\n    \"Bad Rate valueset\",        \\\n    \"Bad Band\",         \\\n    \"Buffer too short\",     \\\n    \"Buffer too long\",      \\\n    \"Busy\",             \\\n    \"Not Associated\",       \\\n    \"Bad SSID len\",         \\\n    \"Out of Range Channel\",     \\\n    \"Bad Channel\",          \\\n    \"Bad Address\",          \\\n    \"Not Enough Resources\",     \\\n    \"Unsupported\",          \\\n    \"Bad length\",           \\\n    \"Not Ready\",            \\\n    \"Not Permitted\",        \\\n    \"No Memory\",            \\\n    \"Associated\",           \\\n    \"Not In Range\",         \\\n    \"Not Found\",            \\\n    \"WME Not Enabled\",      \\\n    \"TSPEC Not Found\",      \\\n    \"ACM Not Supported\",        \\\n    \"Not WME Association\",      \\\n    \"SDIO Bus Error\",       \\\n    \"Dongle Not Accessible\"     \\\n}\n\n/* Types definition*/\n/*\n * Inferred Typedefs\n *\n */\n\n/* Infer the compile environment based on preprocessor symbols and pramas.\n * Override type definitions as needed, and include configuration dependent\n * header files to define types.\n */\n\n#ifdef __cplusplus\n\n#define TYPEDEF_BOOL\n#ifndef FALSE\n#define FALSE   false\n#endif\n#ifndef TRUE\n#define TRUE    true\n#endif\n\n#endif\t\t\t\t/* __cplusplus */\n\n#if defined(_NEED_SIZE_T_)\ntypedef long unsigned int size_t;\n#endif\n\n#define TYPEDEF_UINT\n#define TYPEDEF_USHORT\n#define TYPEDEF_ULONG\n\n/* Do not support the (u)int64 types with strict ansi for GNU C */\n#if defined(__GNUC__) && defined(__STRICT_ANSI__)\n#define TYPEDEF_INT64\n#define TYPEDEF_UINT64\n#endif\n\n/* pick up ushort & uint from standard types.h */\n#if defined(linux) && defined(__KERNEL__)\n#include <linux/types.h>\t/* sys/types.h and linux/types.h are oil and water */\n#else\n#include <sys/types.h>\n#endif\n\n/* use the default typedefs in the next section of this file */\n#define USE_TYPEDEF_DEFAULTS\n\n/*\n * Default Typedefs\n *\n */\n\n#ifdef USE_TYPEDEF_DEFAULTS\n#undef USE_TYPEDEF_DEFAULTS\n\n#ifndef TYPEDEF_BOOL\ntypedef /* @abstract@ */ unsigned char bool;\n#endif\n\n/* define uchar, ushort, uint, ulong */\n\n#ifndef TYPEDEF_UCHAR\ntypedef unsigned char uchar;\n#endif\n\n#ifndef TYPEDEF_USHORT\ntypedef unsigned short ushort;\n#endif\n\n#ifndef TYPEDEF_UINT\ntypedef unsigned int uint;\n#endif\n\n#ifndef TYPEDEF_ULONG\ntypedef unsigned long ulong;\n#endif\n\n/* define [u]int8/16/32/64, uintptr */\n\n#ifndef TYPEDEF_UINT8\ntypedef unsigned char uint8;\n#endif\n\n#ifndef TYPEDEF_UINT16\ntypedef unsigned short uint16;\n#endif\n\n#ifndef TYPEDEF_UINT32\ntypedef unsigned int uint32;\n#endif\n\n#ifndef TYPEDEF_UINT64\ntypedef unsigned long long uint64;\n#endif\n\n#ifndef TYPEDEF_UINTPTR\ntypedef unsigned int uintptr;\n#endif\n\n#ifndef TYPEDEF_INT8\ntypedef signed char int8;\n#endif\n\n#ifndef TYPEDEF_INT16\ntypedef signed short int16;\n#endif\n\n#ifndef TYPEDEF_INT32\ntypedef signed int int32;\n#endif\n\n#ifndef TYPEDEF_INT64\ntypedef signed long long int64;\n#endif\n\n/* define float32/64, float_t */\n\n#ifndef TYPEDEF_FLOAT32\ntypedef float float32;\n#endif\n\n#ifndef TYPEDEF_FLOAT64\ntypedef double float64;\n#endif\n\n/*\n * abstracted floating point type allows for compile time selection of\n * single or double precision arithmetic.  Compiling with -DFLOAT32\n * selects single precision; the default is double precision.\n */\n\n#ifndef TYPEDEF_FLOAT_T\n\n#if defined(FLOAT32)\ntypedef float32 float_t;\n#else\t\t\t\t/* default to double precision floating point */\ntypedef float64 float_t;\n#endif\n\n#endif\t\t\t\t/* TYPEDEF_FLOAT_T */\n\n/* define macro values */\n\n#ifndef FALSE\n#define FALSE   0\n#endif\n\n#ifndef TRUE\n#define TRUE    1\t\t/* TRUE */\n#endif\n\n#ifndef NULL\n#define NULL    0\n#endif\n\n#ifndef OFF\n#define OFF 0\n#endif\n\n#ifndef ON\n#define ON  1\t\t\t/* ON = 1 */\n#endif\n\n#define AUTO    (-1)\t\t/* Auto = -1 */\n\n/* define PTRSZ, INLINE */\n\n#ifndef PTRSZ\n#define PTRSZ   sizeof(char*)\n#endif\n\n#ifndef INLINE\n\n#ifdef _MSC_VER\n\n#define INLINE __inline\n\n#elif __GNUC__\n\n#define INLINE __inline__\n\n#else\n\n#define INLINE\n\n#endif\t\t\t\t/* _MSC_VER */\n\n#endif\t\t\t\t/* INLINE */\n\n#undef TYPEDEF_BOOL\n#undef TYPEDEF_UCHAR\n#undef TYPEDEF_USHORT\n#undef TYPEDEF_UINT\n#undef TYPEDEF_ULONG\n#undef TYPEDEF_UINT8\n#undef TYPEDEF_UINT16\n#undef TYPEDEF_UINT32\n#undef TYPEDEF_UINT64\n#undef TYPEDEF_UINTPTR\n#undef TYPEDEF_INT8\n#undef TYPEDEF_INT16\n#undef TYPEDEF_INT32\n#undef TYPEDEF_INT64\n#undef TYPEDEF_FLOAT32\n#undef TYPEDEF_FLOAT64\n#undef TYPEDEF_FLOAT_T\n\n/* WME Access Category Indices (ACIs) */\n#define AC_BE           0\t/* Best Effort */\n#define AC_BK           1\t/* Background */\n#define AC_VI           2\t/* Video */\n#define AC_VO           3\t/* Voice */\n#define AC_COUNT        4\t/* number of ACs */\n\nstruct edcf_acparam {\n\tuint8 ACI;\n\tuint8 ECW;\n\tuint16 TXOP;\t\t/* stored in network order (ls octet first) */\n} PACKED;\ntypedef struct edcf_acparam edcf_acparam_t;\n\n/* Linux network driver ioctl encoding */\ntypedef struct wl_ioctl {\n\tuint cmd;\t\t/* common ioctl definition */\n\tvoid *buf;\t\t/* pointer to user buffer */\n\tuint len;\t\t/* length of user buffer */\n\tbool set;\t\t/* get or set request (optional) */\n\tuint used;\t\t/* bytes read or written (optional) */\n\tuint needed;\t\t/* bytes needed (optional) */\n} wl_ioctl_t;\n\n/*\n * Pass a wlioctl request to the specified interface.\n * @param   name    interface name\n * @param   cmd WLC_GET_MAGIC <= cmd < WLC_LAST\n * @param   buf buffer for passing in and/or receiving data\n * @param   len length of buf\n * @return  >= 0 if successful or < 0 otherwise\n */\nextern int wl_ioctl(char *name, int cmd, void *buf, int len);\n\nextern int wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen);\nextern int wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen);\n/*\n * Set/Get named variable.\n * @param   ifname      interface name\n * @param   iovar       variable name\n * @param   param       input param value/buffer\n * @param   paramlen    input param value/buffer length\n * @param   bufptr      io buffer\n * @param   buflen      io buffer length\n * @param   val     val or val pointer for int routines\n * @return  success == 0, failure != 0\n */\n/*\n * set named driver variable to int value\n * calling example: wl_iovar_setint(ifname, \"arate\", rate)\n*/\nstatic inline int wl_iovar_setint(char *ifname, char *iovar, int val)\n{\n\treturn wl_iovar_set(ifname, iovar, &val, sizeof(val));\n}\n\n/*\n * get named driver variable to int value and return error indication\n * calling example: wl_iovar_getint(ifname, \"arate\", &rate)\n */\nstatic inline int wl_iovar_getint(char *ifname, char *iovar, int *val)\n{\n\treturn wl_iovar_get(ifname, iovar, val, sizeof(int));\n}\n\n#endif\n"
  },
  {
    "path": "WTPBcmFrameReceive.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"WTPBcmFrameReceive.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nint extractFrame(CWProtocolMessage ** frame, unsigned char *buffer, int len)\t//len: frame length\n{\n\tCW_CREATE_OBJECT_ERR(*frame, CWProtocolMessage, return 0;\n\t    );\n\tCWProtocolMessage *auxPtr = *frame;\n\tCW_CREATE_PROTOCOL_MESSAGE(*auxPtr, len, return 0;\n\t    );\n\tmemcpy(auxPtr->msg, buffer, len);\n\tauxPtr->offset = len;\n\treturn 1;\n}\n\nint get_mac(u_char * buf)\n{\n\tstruct ifreq ifr;\n\tint s;\n\n\t/* open socket to kernel */\n\tif ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {\n\t\tperror(\"socket\");\n\t\treturn errno;\n\t}\n\n\tstrncpy(ifr.ifr_name, WL_DEVICE, IFNAMSIZ);\n\t//ifr.ifr_data = (caddr_t) buf;\n\tif ((ioctl(s, SIOCGIFHWADDR, &ifr)) < 0) {\n\n\t\tperror(ifr.ifr_name);\n\t\tclose(s);\n\t\treturn 0;\n\t}\n\n\t/* cleanup */\n\tclose(s);\n\tmemcpy(buf, &(ifr.ifr_hwaddr.sa_data), MAC_ADDR_LEN);\n\treturn 1;\n}\n\nint macAddrCmp(unsigned char *addr1, unsigned char *addr2)\n{\n\tint i, ok = 1;\n\n\t/*  CWDebugLog(\"Address 1:\");\n\t   for (i=0; i<MAC_ADDR_LEN; i++)\n\t   {\n\t   CWDebugLog(\"%02x \", addr1[i]);\n\t   }\n\n\t   CWDebugLog(\"\\nAddress 2:\");\n\t   for (i=0; i<MAC_ADDR_LEN; i++)\n\t   {\n\t   CWDebugLog(\"%02x \", addr2[i]);\n\t   }\n\t   CWDebugLog(\"\\n\"); */\n\n\tfor (i = 0; i < MAC_ADDR_LEN; i++) {\n\t\tif (addr1[i] != addr2[i]) {\n\t\t\tok = 0;\n\t\t}\n\t}\n\n\treturn ok;\n}\n\nvoid print_mac(u_char * mac, char *extra)\n{\n\tfprint_mac(stdout, mac, extra);\n}\n\nvoid fprint_mac(FILE * outf, u_char * mac, char *extra)\n{\n\tfprintf(outf, \"%02X:%02X:%02X:%02X:%02X:%02X%s\",\n\t\tmac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF, mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF, extra);\n}\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveFrame(void *arg)\n{\n\tpcap_t *handle;\n\tchar *dev;\n\tchar errbuf[PCAP_ERRBUF_SIZE];\n\tint oldMonitor, newMonitor;\n\tstruct pcap_pkthdr header;\n\tu_char wl0_mac_address[MAC_ADDR_LEN];\t// interface mac address\n\tconst u_char *packet;\n\tint i;\n\tprintf(\"2: CWWTPReceiveFrame\\n\");\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n\t//Get interface mac address\n\tif (!get_mac(wl0_mac_address)) {\n\n\t\tCWDebugLog(\"THR FRAME: Failure to get interface mac address\");\n\tEXIT_THREAD}\n\n\t/*Set interface in a special monitor mode throws WL_GET_MAGIC & WLC_GET_MONITOR */\n\twl_ioctl(WL_DEVICE, WLC_GET_MAGIC, &i, 4);\n\tif (i != WLC_IOCTL_MAGIC) {\n\n\t\tCWDebugLog(\"THR FRAME: Wireless magic not correct, not querying wl for info\");\n\tEXIT_THREAD} else {\n\t\twl_ioctl(WL_DEVICE, WLC_GET_MONITOR, &oldMonitor, 4);\n\t\tnewMonitor = 1;\n\t\twl_ioctl(WL_DEVICE, WLC_SET_MONITOR, &newMonitor, 4);\n\t}\n\n\tdev = \"prism0\";\n\thandle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);\n\n\tif (!handle) {\n\n\t\tCWDebugLog(\"THR FRAME: Failure to open pcap!\");\n\tEXIT_THREAD}\n\n\tCW_REPEAT_FOREVER {\n\n\t\tpacket = pcap_next(handle, &header);\n\t\tif (!packet)\n\t\t\tbreak;\n\t\tdealWithPacket(&header, packet, wl0_mac_address);\n\t}\n\n\twl_ioctl(WL_DEVICE, WLC_SET_MONITOR, &oldMonitor, 4);\n\tpcap_close(handle);\n\n\treturn (NULL);\n}\n\n//////////////////////////////////////////////////////////////////////////////////\nvoid dealWithPacket(struct pcap_pkthdr *header, const u_char * packet, u_char * wl0_mac_address)\n{\n\tieee802_11_hdr *hWifi;\n\tprism_hdr *hPrism;\n\tint wfType, packet_len;\n\tchar RSSI = 0, SNR = 0;\n\tint data_rate = 0;\n\tprism_did *i;\n\tchar *src = \"\\0\\0\\0\\0\\0\\0\";\n\tchar *dst = \"\\0\\0\\0\\0\\0\\0\";\n\tCWBindingTransportHeaderValues *bindingValuesPtr = NULL;\n\tCWProtocolMessage *frame = NULL;\n\tCWBindingDataListElement *listElement = NULL;\n\tunsigned char *buffer = NULL;\n\n\tif (!packet)\n\t\treturn;\n\tif (header->len < sizeof(prism_hdr) + sizeof(ieee802_11_hdr))\n\t\treturn;\n\thPrism = (prism_hdr *) packet;\n\thWifi = (ieee802_11_hdr *) (packet + (hPrism->msg_length));\n\tbuffer = (unsigned char *)(packet + (hPrism->msg_length));\n\tpacket_len = hPrism->msg_length;\n\n\tif (!macAddrCmp(hWifi->addr1, wl0_mac_address))\n\t\treturn;\n\n\t//Parse the prism DIDs\n\ti = (prism_did *) ((char *)hPrism + sizeof(prism_hdr));\n\twhile ((int)i < (int)hWifi) {\n\t\tif (i->did == pdn_rssi)\n\t\t\tRSSI = *(char *)(i + 1);\n\t\tif (i->did == pdn_sq)\n\t\t\tSNR = *(char *)(i + 1);\n\t\tif (i->did == pdn_datarate)\n\t\t\tdata_rate = (((*(int *)(i + 1)) / 2) * 10);\n\t\ti = (prism_did *) ((int)(i + 1) + i->length);\n\t}\n\n\t//Establish the frame type\n\twfType = ((hWifi->frame_control & 0xF0) >> 4) + ((hWifi->frame_control & 0xC) << 2);\n\tswitch (wfType) {\n\tcase mgt_assocRequest:\n\t\tsrc = hWifi->addr2;\n\t\tdst = hWifi->addr1;\n\t\tprintf(\"\\nAssociation request received from: \");\n\t\tprint_mac(src, \"\\n\");\n\t\tfflush(stdout);\n\t\t//CWDebugLog(\"\\nRSSI: %d\",RSSI);\n\t\t//CWDebugLog(\"\\nSNR: %d\",SNR);\n\t\t//CWDebugLog(\"\\nData Rate: %d Mbs\\n\",data_rate);\n\t\tCW_CREATE_OBJECT_ERR(bindingValuesPtr, CWBindingTransportHeaderValues, EXIT_THREAD);\n\t\tbindingValuesPtr->RSSI = RSSI;\n\t\tbindingValuesPtr->SNR = SNR;\n\t\tbindingValuesPtr->dataRate = data_rate;\n\t\tCW_CREATE_OBJECT_ERR(listElement, CWBindingDataListElement, EXIT_THREAD);\n\t\tif (!extractFrame(&frame, buffer, packet_len - sizeof(prism_hdr))) {\n\t\t\tCWDebugLog(\"THR FRAME: Error extracting a frame\");\n\t\tEXIT_THREAD}\n\t\tlistElement->frame = frame;\n\t\tlistElement->bindingValues = bindingValuesPtr;\n\n\t\tCWLockSafeList(gFrameList);\n\t\tCWAddElementToSafeListTail(gFrameList, listElement, sizeof(CWBindingDataListElement));\n\t\tCWUnlockSafeList(gFrameList);\n\t\tbreak;\n\n\tcase mgt_assocResponse:\n\t\tbreak;\n\tcase mgt_reassocRequest:\n\t\tbreak;\n\tcase mgt_reassocResponse:\n\t\tbreak;\n\tcase mgt_probeRequest:\n\t\tbreak;\n\tcase mgt_probeResponse:\n\t\tbreak;\n\tcase mgt_beacon:\n\t\tbreak;\n\tcase mgt_disassoc:\n\t\tbreak;\n\tcase mgt_auth:\n\t\tbreak;\n\tcase mgt_deauth:\n\t\tbreak;\n\t}\n\n}\n"
  },
  {
    "path": "WTPBcmFrameReceive.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_WTPFrameReceive_HEADER__\n#define __CAPWAP_WTPFrameReceive_HEADER__\n\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <linux/if_ether.h>\n#include <net/if.h>\n#include <sys/ioctl.h>\n#include <pcap.h>\n\n#include \"CWWTP.h\"\n\n#define EXIT_THREAD     CWLog(\"ERROR Handling Frames: application will be closed!\");        \\\n                exit(1);\n\n#define WL_DEVICE \"wl0\"\n#define MAC_ADDR_LEN        6\n\n/* check this magic number */\n#define WLC_IOCTL_MAGIC     0x14e46c77\n\n#define WLC_GET_MAGIC               0\n#define WLC_GET_BSSID               23\n#define WLC_SET_BSSID               24\n#define WLC_GET_SSID                25\n#define WLC_SET_SSID                26\n#define WLC_GET_CHANNEL             29\n#define WLC_SET_CHANNEL             30\n#define WLC_GET_MONITOR             107\t/* discovered by nbd */\n#define WLC_SET_MONITOR             108\t/* discovered by nbd */\n#define WLC_GET_AP              117\n#define WLC_SET_AP              118\n#define WLC_GET_RSSI                127\n#define WLC_GET_ASSOCLIST           159\n\n#ifdef DEFINE_TYPES\ntypedef unsigned short u_short;\ntypedef unsigned char u_char;\ntypedef unsigned int u_int;\n#endif\n\ntypedef enum {\n\tmgt_assocRequest = 0,\n\tmgt_assocResponse = 1,\n\tmgt_reassocRequest = 2,\n\tmgt_reassocResponse = 3,\n\tmgt_probeRequest = 4,\n\tmgt_probeResponse = 5,\n\tmgt_beacon = 8,\n\tmgt_disassoc = 10,\n\tmgt_auth = 11,\n\tmgt_deauth = 12\n} wifi_frametype;\n\ntypedef struct ieee802_11_hdr {\n\tu_char frame_control;\n\tu_char flags;\n#define IEEE80211_TO_DS 0x01\n#define IEEE80211_FROM_DS 0x02\n#define IEEE80211_MORE_FRAG 0x04\n#define IEEE80211_RETRY 0x08\n#define IEEE80211_PWR_MGT 0x10\n#define IEEE80211_MORE_DATA 0x20\n#define IEEE80211_WEP_FLAG 0x40\n#define IEEE80211_ORDER_FLAG 0x80\n\tu_short duration;\n\tu_char addr1[6];\n\tu_char addr2[6];\n\tu_char addr3[6];\n\tu_short frag_and_seq;\n} ieee802_11_hdr;\n\ntypedef struct {\n\tu_char timestamp[8];\n\tu_short bcn_interval;\n\tu_short caps;\n#define MGT_CAPS_AP 0x1\n#define MGT_CAPS_IBSS 0x2\n#define MGT_CAPS_WEP 0x10\n} ieee_802_11_mgt_frame;\n\ntypedef struct prism_hdr {\n\tu_int msg_code;\n\tu_int msg_length;\n\tchar cap_device[16];\n} prism_hdr;\n\ntypedef struct prism_did {\n\tu_short did;\n\tu_short status1;\n\tu_short status2;\n\tu_short length;\n\n} prism_did;\n\ntypedef enum prism_did_num {\n\tpdn_host_time = 0x1041,\n\tpdn_mac_time = 0x2041,\n\tpdn_rssi = 0x4041,\n\tpdn_sq = 0x5041,\n\tpdn_datarate = 0x8041,\n\tpdn_framelen = 0xa041\n} prism_did_num;\n\nvoid print_mac(u_char * mac, char *extra);\nvoid fprint_mac(FILE * outf, u_char * mac, char *extra);\nint macAddrCmp(unsigned char *addr1, unsigned char *addr2);\nint get_mac(u_char * buf);\nvoid dealWithPacket(struct pcap_pkthdr *header, const u_char * packet, u_char * wl0_mac_address);\n#endif\n"
  },
  {
    "path": "WTPBinding.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#include \"wireless_copy.h\"\n#include \"CWWTP.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include <unistd.h>\n#include <signal.h>\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nint CWTranslateQueueIndex(int j)\n{\n\tif (j == VOICE_QUEUE_INDEX)\n\t\treturn 3;\n\tif (j == VIDEO_QUEUE_INDEX)\n\t\treturn 2;\n\tif (j == BACKGROUND_QUEUE_INDEX)\n\t\treturn 1;\n\n\treturn 0;\n}\n\n#ifdef SOFTMAC\nCWBool CWWTPInitBinding(int radioIndex)\n{\n\n\tbindingValues *aux;\n\tint i;\n\n\tCW_CREATE_OBJECT_ERR(aux, bindingValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tgRadiosInfo.radiosInfo[radioIndex].bindingValuesPtr = (void *)aux;\n\n\tCW_CREATE_ARRAY_ERR(aux->qosValues, NUM_QOS_PROFILES, WTPQosValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < NUM_QOS_PROFILES; i++) {\n\t\t/* TODO: Get info from Hostapd UNIX DOMAIN SOCKET */\n\t\taux->qosValues[i].cwMin = 3;\n\t\taux->qosValues[i].cwMax = 15;\n\t\taux->qosValues[i].AIFS = 2;\n\t}\n\n\treturn CW_TRUE;\n}\n\n#else\n\n#ifndef BCM\nCWBool CWWTPInitBinding(int radioIndex)\n{\n\n\tbindingValues *aux;\n\tint i, sock;\n\tstruct iwreq wrq;\n\n\t/*** Inizializzazione socket ***/\n\tsock = socket(AF_INET, SOCK_DGRAM, 0);\n\n\tif (sock < 0) {\n\n\t\tCWLog(\"Error Creating Socket for ioctl\");\n\t\treturn CW_FALSE;\n\t}\n\n\t/*** Inizializzazione struttura iwreq ***/\n\tmemset(&wrq, 0, sizeof(wrq));\n\tstrncpy(wrq.ifr_name, gInterfaceName, IFNAMSIZ);\n\n\tCWLog(\"wrq.ifr_name %s \", wrq.ifr_name);\n\n\tCW_CREATE_OBJECT_ERR(aux, bindingValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tgRadiosInfo.radiosInfo[radioIndex].bindingValuesPtr = (void *)aux;\n\n\tCW_CREATE_ARRAY_ERR(aux->qosValues, NUM_QOS_PROFILES, WTPQosValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < NUM_QOS_PROFILES; i++) {\n\n\t\t/*\n\t\t * Donato Capitella - TO_REMOVE_DEVELOP\n\t\t * Commented the following lines just to make the WTP work in a test machine.\n\t\t */\n\t\t//if(!get_cwmin(sock, &wrq, CWTranslateQueueIndex(i), 0)){return CW_FALSE;}\n\n\t\t//aux->qosValues[i].cwMin = wrq.u.param.value;\n\n\t\t//if(!get_cwmax(sock, &wrq, CWTranslateQueueIndex(i), 0)){return CW_FALSE;}\n\t\t//aux->qosValues[i].cwMax = wrq.u.param.value;\n\n\t\t//if(!get_aifs(sock, &wrq, CWTranslateQueueIndex(i), 0)){return CW_FALSE;}\n\t\t//aux->qosValues[i].AIFS = wrq.u.param.value;\n\n\t\t/*##        aux->qosValues[i].cwMin = 2;\n\t\t   aux->qosValues[i].cwMax = 4;\n\t\t   aux->qosValues[i].AIFS = 3;\n\t\t */\n\t}\n\n\treturn CW_TRUE;\n}\n\n#else\nCWBool CWWTPInitBinding(int radioIndex)\n{\n\n\tbindingValues *aux;\n\tint i;\n\n\tCW_CREATE_OBJECT_ERR(aux, bindingValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tgRadiosInfo.radiosInfo[radioIndex].bindingValuesPtr = (void *)aux;\n\n\tCW_CREATE_ARRAY_ERR(aux->qosValues, NUM_QOS_PROFILES, WTPQosValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < NUM_QOS_PROFILES; i++) {\n\t\t/*Daniele: i driver Broadcom non permettono get sulle WME: setto i parametri del Qos a valori costanti */\n\t\taux->qosValues[i].cwMin = 2;\n\t\taux->qosValues[i].cwMax = 4;\n\t\taux->qosValues[i].AIFS = 3;\n\t}\n\n\treturn CW_TRUE;\n}\n#endif\n\n#endif\n\n#ifdef SOFTMAC\n\nCWBool CWBindingSetQosValues(int qosCount, RadioQosValues * radioQosValues, CWProtocolResultCode * resultCode)\n{\n\n\tif (qosCount <= 0) {\n\t\treturn CW_TRUE;\n\t}\n\tif (radioQosValues == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tint i, k, j;\n\n\tfor (i = 0; i < qosCount; i++) {\n\t\tfor (k = 0; k < gRadiosInfo.radioCount; k++) {\n\t\t\tif (radioQosValues[i].radioID == gRadiosInfo.radiosInfo[k].radioID) {\n\t\t\t\tbindingValues *auxPtr = (bindingValues *) gRadiosInfo.radiosInfo[k].bindingValuesPtr;\n\n\t\t\t\tfor (j = 0; j < NUM_QOS_PROFILES; j++) {\n\n\t\t\t\t\tCWLog(\"AIFS:  %d    %d\", auxPtr->qosValues[j].AIFS,\n\t\t\t\t\t      radioQosValues[i].qosValues[j].AIFS);\n\n\t\t\t\t\tint aifs = (int)radioQosValues[i].qosValues[j].AIFS;\n\t\t\t\t\tint burst_time = 0;\n\t\t\t\t\tif (j == 0)\n\t\t\t\t\t\tburst_time = 15;\n\t\t\t\t\telse if (j == 1)\n\t\t\t\t\t\tburst_time = 30;\n\n\t\t\t\t\tif (set_txq\n\t\t\t\t\t    (j, radioQosValues[i].qosValues[j].cwMin,\n\t\t\t\t\t     radioQosValues[i].qosValues[j].cwMax, aifs, burst_time)) {\n\t\t\t\t\t\tauxPtr->qosValues[j].cwMin = radioQosValues[i].qosValues[j].cwMin;\n\t\t\t\t\t\tauxPtr->qosValues[j].cwMax = radioQosValues[i].qosValues[j].cwMax;\n\t\t\t\t\t\tauxPtr->qosValues[j].AIFS = radioQosValues[i].qosValues[j].AIFS;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t   if(auxPtr->qosValues[j].cwMin!=radioQosValues[i].qosValues[j].cwMin)\n\t\t\t\t\t   {\n\t\t\t\t\t   if (set_wme_cwmin(CWTranslateQueueIndex(j), radioQosValues[i].qosValues[j].cwMin))\n\t\t\t\t\t   {auxPtr->qosValues[j].cwMin=radioQosValues[i].qosValues[j].cwMin;}\n\t\t\t\t\t   else {*resultCode=CW_PROTOCOL_FAILURE;}\n\t\t\t\t\t   }\n\n\t\t\t\t\t   if(auxPtr->qosValues[j].cwMax!=radioQosValues[i].qosValues[j].cwMax)\n\t\t\t\t\t   {\n\t\t\t\t\t   if (set_wme_cwmax(CWTranslateQueueIndex(j), radioQosValues[i].qosValues[j].cwMax))\n\t\t\t\t\t   {auxPtr->qosValues[j].cwMax=radioQosValues[i].qosValues[j].cwMax;}\n\t\t\t\t\t   else {*resultCode=CW_PROTOCOL_FAILURE;}\n\t\t\t\t\t   }\n\n\t\t\t\t\t   if(auxPtr->qosValues[j].AIFS!=radioQosValues[i].qosValues[j].AIFS)\n\t\t\t\t\t   {\n\t\t\t\t\t   if (set_wme_aifsn(CWTranslateQueueIndex(j), radioQosValues[i].qosValues[j].AIFS))\n\t\t\t\t\t   {auxPtr->qosValues[j].AIFS=radioQosValues[i].qosValues[j].AIFS;}\n\t\t\t\t\t   else {*resultCode=CW_PROTOCOL_FAILURE;}\n\t\t\t\t\t   }\n\t\t\t\t\t */\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n\n#else\n\n#ifndef BCM\nCWBool CWBindingSetQosValues(int qosCount, RadioQosValues * radioQosValues, CWProtocolResultCode * resultCode)\n{\n\tstruct iwreq wrq;\n\tint sock;\n\n\tif (qosCount <= 0) {\n\t\treturn CW_TRUE;\n\t}\n\tif (radioQosValues == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\t/*** Inizializzazione socket ***/\n\tsock = socket(AF_INET, SOCK_DGRAM, 0);\n\tif (sock < 0) {\n\t\tCWLog(\"Error Creating Socket for ioctl\");\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);;\n\t}\n\n\t/*** Inizializzazione struttura iwreq ***/\n\tmemset(&wrq, 0, sizeof(wrq));\n\tstrncpy(wrq.ifr_name, gInterfaceName, IFNAMSIZ);\n\n\tint i, k, j;\n\n\tfor (i = 0; i < qosCount; i++) {\n\t\tfor (k = 0; k < gRadiosInfo.radioCount; k++) {\n\t\t\tif (radioQosValues[i].radioID == gRadiosInfo.radiosInfo[k].radioID) {\n\t\t\t\tbindingValues *auxPtr = (bindingValues *) gRadiosInfo.radiosInfo[k].bindingValuesPtr;\n\n\t\t\t\tfor (j = 0; j < NUM_QOS_PROFILES; j++) {\n\t\t\t\t\tif (auxPtr->qosValues[j].cwMin != radioQosValues[i].qosValues[j].cwMin) {\n\t\t\t\t\t\tif (set_cwmin\n\t\t\t\t\t\t    (sock, wrq, CWTranslateQueueIndex(j), 0,\n\t\t\t\t\t\t     radioQosValues[i].qosValues[j].cwMin)) {\n\t\t\t\t\t\t\tauxPtr->qosValues[j].cwMin =\n\t\t\t\t\t\t\t    radioQosValues[i].qosValues[j].cwMin;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (auxPtr->qosValues[j].cwMax != radioQosValues[i].qosValues[j].cwMax) {\n\t\t\t\t\t\tif (set_cwmax\n\t\t\t\t\t\t    (sock, wrq, CWTranslateQueueIndex(j), 0,\n\t\t\t\t\t\t     radioQosValues[i].qosValues[j].cwMax)) {\n\t\t\t\t\t\t\tauxPtr->qosValues[j].cwMax =\n\t\t\t\t\t\t\t    radioQosValues[i].qosValues[j].cwMax;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (auxPtr->qosValues[j].AIFS != radioQosValues[i].qosValues[j].AIFS) {\n\t\t\t\t\t\tif (set_aifs\n\t\t\t\t\t\t    (sock, wrq, CWTranslateQueueIndex(j), 0,\n\t\t\t\t\t\t     radioQosValues[i].qosValues[j].AIFS)) {\n\t\t\t\t\t\t\tauxPtr->qosValues[j].AIFS = radioQosValues[i].qosValues[j].AIFS;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t//WTPQosValues* aux=radioQosValues;\n\n\tclose(sock);\n\treturn CW_TRUE;\n}\n\n#else\n\nCWBool CWBindingSetQosValues(int qosCount, RadioQosValues * radioQosValues, CWProtocolResultCode * resultCode)\n{\n\n\tif (qosCount <= 0) {\n\t\treturn CW_TRUE;\n\t}\n\tif (radioQosValues == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tint i, k, j;\n\n\tfor (i = 0; i < qosCount; i++) {\n\t\tfor (k = 0; k < gRadiosInfo.radioCount; k++) {\n\t\t\tif (radioQosValues[i].radioID == gRadiosInfo.radiosInfo[k].radioID) {\n\t\t\t\tbindingValues *auxPtr = (bindingValues *) gRadiosInfo.radiosInfo[k].bindingValuesPtr;\n\n\t\t\t\tfor (j = 0; j < NUM_QOS_PROFILES; j++) {\n\n\t\t\t\t\tif (auxPtr->qosValues[j].cwMin != radioQosValues[i].qosValues[j].cwMin) {\n\t\t\t\t\t\tif (set_wme_cwmin\n\t\t\t\t\t\t    (CWTranslateQueueIndex(j), radioQosValues[i].qosValues[j].cwMin)) {\n\t\t\t\t\t\t\tauxPtr->qosValues[j].cwMin =\n\t\t\t\t\t\t\t    radioQosValues[i].qosValues[j].cwMin;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (auxPtr->qosValues[j].cwMax != radioQosValues[i].qosValues[j].cwMax) {\n\t\t\t\t\t\tif (set_wme_cwmax\n\t\t\t\t\t\t    (CWTranslateQueueIndex(j), radioQosValues[i].qosValues[j].cwMax)) {\n\t\t\t\t\t\t\tauxPtr->qosValues[j].cwMax =\n\t\t\t\t\t\t\t    radioQosValues[i].qosValues[j].cwMax;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (auxPtr->qosValues[j].AIFS != radioQosValues[i].qosValues[j].AIFS) {\n\t\t\t\t\t\tif (set_wme_aifsn\n\t\t\t\t\t\t    (CWTranslateQueueIndex(j), radioQosValues[i].qosValues[j].AIFS)) {\n\t\t\t\t\t\t\tauxPtr->qosValues[j].AIFS = radioQosValues[i].qosValues[j].AIFS;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t*resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n\n#endif\n\n#endif\n\n/**************************************************************\n * Update 2009: OFDM Message Element Management               *\n **************************************************************/\n\nCWBool CWManageOFDMValues(CWBindingConfigurationUpdateRequestValuesOFDM * ofdmValues, CWProtocolResultCode * resultCode)\n{\n\n\tif (ofdmValues == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tOFDMControlValues *radioValues = ofdmValues->radioOFDMValues;\n\t//unsigned char radioID = ofdmValues->radioID;\n\n\tstruct sockaddr_in serv_addr;\n\tint sendSock, slen = sizeof(serv_addr);\n\n\tif ((sendSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {\n\t\tCWLog(\"[FreqAnalyzer]: Error on creation of socket.\");\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\tmemset(&serv_addr, 0, sizeof(serv_addr));\n\tserv_addr.sin_family = AF_INET;\n\tserv_addr.sin_port = htons(FREQ_SERVER_PORT);\n\n\tif (inet_aton(FREQ_SERVER_ADDR, &serv_addr.sin_addr) == 0) {\n\t\tCWLog(\"[CWManageOFDMValue]: Error on aton function.\");\n\t\tclose(sendSock);\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\t/********************************************************************\n\t * Update 2009: OFDM Management                                     *\n\t *                                                                  *\n\t * Send a OFDMControlValues to wtpFreqManager.                      *\n\t * In this function there is the control switch for the different   *\n\t * type of commands.                                                *\n\t ********************************************************************/\n\n\tif (sendto(sendSock, radioValues, sizeof(OFDMControlValues), 0, (struct sockaddr *)&serv_addr, slen) < 0) {\n\t\tCWLog(\"[CWManageOFDMValue]: Error on sendto function.\");\n\t\tclose(sendSock);\n\t\treturn CWErrorRaise(CW_ERROR_GENERAL, NULL);\n\t}\n\n\tclose(sendSock);\n\treturn CW_TRUE;\n}\n\nCWBool CWParseWTPOFDM(CWProtocolMessage * msgPtr, int len, unsigned char *radioID, OFDMControlValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\t*radioID = CWProtocolRetrieve8(msgPtr);\n\n\tvalPtr->currentChan = CWProtocolRetrieve32(msgPtr);\n\tvalPtr->BandSupport = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\tvalPtr->TIThreshold = (unsigned int)CWProtocolRetrieve32(msgPtr);\n\n\tCWParseMessageElementEnd();\n\n}\n\nCWBool CWParseWTPQoS(CWProtocolMessage * msgPtr, int len, unsigned char *radioID, unsigned char *tagPackets,\n\t\t     WTPQosValues * valPtr)\n{\n\tint i;\n\n\tCWParseMessageElementStart();\n\n\t*radioID = CWProtocolRetrieve8(msgPtr);\n\t*tagPackets = CWProtocolRetrieve8(msgPtr);\n\n\tfor (i = 0; i < NUM_QOS_PROFILES; i++) {\n\t\tvalPtr[i].queueDepth = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\t\tvalPtr[i].cwMin = CWProtocolRetrieve16(msgPtr);\n\t\tvalPtr[i].cwMax = CWProtocolRetrieve16(msgPtr);\n\t\tvalPtr[i].AIFS = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\t\tvalPtr[i].dot1PTag = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\t\tvalPtr[i].DSCPTag = (unsigned char)CWProtocolRetrieve8(msgPtr);\n\t}\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWBindingSaveConfigurationUpdateRequest(void *bindingValuesPtr, CWProtocolResultCode * resultCode,\n\t\t\t\t\t       int *updateRequestType)\n{\n\tif (bindingValuesPtr == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tswitch (*updateRequestType) {\n\tcase BINDING_MSG_ELEMENT_TYPE_WTP_QOS:{\n\n\t\t\tCWBindingConfigurationUpdateRequestValues *bindingPtr =\n\t\t\t    (CWBindingConfigurationUpdateRequestValues *) bindingValuesPtr;\n\n\t\t\tif (bindingPtr->qosCount > 0) {\n\t\t\t\tif (!CWBindingSetQosValues\n\t\t\t\t    (bindingPtr->qosCount, bindingPtr->radioQosValues, resultCode)) {\n\t\t\t\t\tCW_FREE_OBJECT(bindingPtr->radioQosValues);\n\t\t\t\t\tCW_FREE_OBJECT(bindingPtr);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t\tCW_FREE_OBJECT(bindingPtr->radioQosValues);\n\t\t\t\tCW_FREE_OBJECT(bindingPtr);\n\t\t\t}\n\t\t\treturn CW_TRUE;\n\t\t\tbreak;\n\t\t}\n\tcase BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL:{\n\t\t\tCWBindingConfigurationUpdateRequestValuesOFDM *bindingPtr =\n\t\t\t    (CWBindingConfigurationUpdateRequestValuesOFDM *) bindingValuesPtr;\n\n\t\t\tif (!CWManageOFDMValues(bindingPtr, resultCode)) {\n\t\t\t\tCW_FREE_OBJECT(bindingPtr->radioOFDMValues);\n\t\t\t\tCW_FREE_OBJECT(bindingPtr);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\n\t\t\treturn CW_TRUE;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWBindingParseConfigurationUpdateRequest(unsigned char *msg, int len, void **valuesPtr)\n{\n\tint i;\n\tCWProtocolMessage completeMsg;\n\tunsigned short int GlobalElemType = 0;\t// = CWProtocolRetrieve32(&completeMsg);\n\tint qosCount = 0;\n\n\tif (msg == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing Binding Configuration Update Request...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tCWBindingConfigurationUpdateRequestValues *auxBindingPtr;\n\tCWBindingConfigurationUpdateRequestValuesOFDM *ofdmBindingPtr;\n\tCW_CREATE_OBJECT_ERR(auxBindingPtr, CWBindingConfigurationUpdateRequestValues,\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t);\n\tCW_CREATE_OBJECT_ERR(ofdmBindingPtr, CWBindingConfigurationUpdateRequestValuesOFDM,\n\t\t\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t);\n\n\t// parse message elements\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int elemType = 0;\t// = CWProtocolRetrieve32(&completeMsg);\n\t\tunsigned short int elemLen = 0;\t// = CWProtocolRetrieve16(&completeMsg);\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\tGlobalElemType = elemType;\n\n\t\t//CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase BINDING_MSG_ELEMENT_TYPE_WTP_QOS:\n\t\t\tqosCount++;\n\t\t\t//(auxBindingPtr->qosCount)++; // just count\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tcase BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL:\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (CWBindingCheckType(elemType)) {\n\t\t\t\tCW_FREE_OBJECT(valuesPtr);\n\t\t\t\tCW_FREE_OBJECT(auxBindingPtr);\n\t\t\t\tCW_FREE_OBJECT(ofdmBindingPtr);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t\t} else {\n\t\t\t\tcompleteMsg.offset += elemLen;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len){\n\t\tCW_FREE_OBJECT(auxBindingPtr);\n\t\tCW_FREE_OBJECT(ofdmBindingPtr);\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\t}\n\n\tswitch (GlobalElemType) {\n\tcase BINDING_MSG_ELEMENT_TYPE_WTP_QOS:{\n\t\t\tCW_FREE_OBJECT(ofdmBindingPtr);\n\t\t\t*valuesPtr = (void *)auxBindingPtr;\n\n\t\t\tauxBindingPtr->qosCount = qosCount;\n\t\t\tauxBindingPtr->radioQosValues = NULL;\n\n\t\t\tCW_CREATE_ARRAY_ERR(auxBindingPtr->radioQosValues, auxBindingPtr->qosCount, RadioQosValues,\n\t\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tbreak;\n\t\t}\n\tcase BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL:\n\t\tCW_FREE_OBJECT(auxBindingPtr);\n\n\t\t*valuesPtr = (void *)ofdmBindingPtr;\n\n\t\tCW_CREATE_OBJECT_ERR(ofdmBindingPtr->radioOFDMValues, OFDMControlValues,\n\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tbreak;\n\tdefault:\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\"Message elemet type unrecognized\"); \n\t}\n\n\ti = 0;\n\tcompleteMsg.offset = 0;\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int type = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &elemLen);\n\n\t\tswitch (type) {\n\t\tcase BINDING_MSG_ELEMENT_TYPE_WTP_QOS:{\n\t\t\t\tunsigned char tagPackets;\n\t\t\t\tif (!\n\t\t\t\t    (CWParseWTPQoS\n\t\t\t\t     (&completeMsg, elemLen, &(auxBindingPtr->radioQosValues[i].radioID), &tagPackets,\n\t\t\t\t      auxBindingPtr->radioQosValues[i].qosValues))) {\n\t\t\t\t\tCW_FREE_OBJECT(auxBindingPtr->radioQosValues);\n\t\t\t\t\tCW_FREE_OBJECT(valuesPtr);\n\t\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL:{\n\t\t\t\t/* 2009: New case */\n\t\t\t\tif (!\n\t\t\t\t    (CWParseWTPOFDM\n\t\t\t\t     (&completeMsg, elemLen, &(ofdmBindingPtr->radioID),\n\t\t\t\t      ofdmBindingPtr->radioOFDMValues))) {\n\t\t\t\t\tCW_FREE_OBJECT(ofdmBindingPtr->radioOFDMValues);\n\t\t\t\t\tCW_FREE_OBJECT(valuesPtr);\n\t\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\tdefault:\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tCWLog(\"Binding Configure Update Request Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWBindingSaveConfigureResponse(void *bindingValuesPtr, CWProtocolResultCode * resultCode)\n{\n\tif (bindingValuesPtr == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tCWBindingConfigurationRequestValues *bindingPtr = (CWBindingConfigurationRequestValues *) bindingValuesPtr;\n\n\tif (bindingPtr->qosCount > 0) {\n\t\tif (!CWBindingSetQosValues(bindingPtr->qosCount, bindingPtr->radioQosValues, resultCode)) {\n\t\t\tCW_FREE_OBJECT(bindingPtr->radioQosValues);\n\t\t\treturn CW_FALSE;\n\t\t}\n\t\tCW_FREE_OBJECT(bindingPtr->radioQosValues);\n\t}\n\treturn CW_TRUE;\n}\n\nCWBool CWBindingParseConfigureResponse(unsigned char *msg, int len, void **valuesPtr)\n{\n\tint i;\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing Binding Configuration Request...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tCWBindingConfigurationRequestValues *auxBindingPtr;\n\tCW_CREATE_OBJECT_ERR(auxBindingPtr, CWBindingConfigurationRequestValues,\n\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*valuesPtr = (void *)auxBindingPtr;\n\n\tauxBindingPtr->qosCount = 0;\n\tauxBindingPtr->radioQosValues = NULL;\n\t// parse message elements\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int elemType = 0;\t// = CWProtocolRetrieve32(&completeMsg);\n\t\tunsigned short int elemLen = 0;\t// = CWProtocolRetrieve16(&completeMsg);\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\tCWDebugLog(\"Parsing Message Element: %d, elemLen: %d\", elemType, elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase BINDING_MSG_ELEMENT_TYPE_WTP_QOS:\n\t\t\t(auxBindingPtr->qosCount)++;\t// just count\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (CWBindingCheckType(elemType)) {\n\t\t\t\tCW_FREE_OBJECT(valuesPtr);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t\t} else {\n\t\t\t\tcompleteMsg.offset += elemLen;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\t// actually read each radio info\n\tCW_CREATE_ARRAY_ERR(auxBindingPtr->radioQosValues, auxBindingPtr->qosCount, RadioQosValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\ti = 0;\n\tcompleteMsg.offset = 0;\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int type = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &elemLen);\n\n\t\tswitch (type) {\n\t\tcase BINDING_MSG_ELEMENT_TYPE_WTP_QOS:{\n\t\t\t\tunsigned char tagPackets;\n\t\t\t\tif (!\n\t\t\t\t    (CWParseWTPQoS\n\t\t\t\t     (&completeMsg, elemLen, &(auxBindingPtr->radioQosValues[i].radioID), &tagPackets,\n\t\t\t\t      auxBindingPtr->radioQosValues[i].qosValues))) {\n\t\t\t\t\tCW_FREE_OBJECT(auxBindingPtr->radioQosValues);\n\t\t\t\t\tCW_FREE_OBJECT(valuesPtr);\n\t\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tdefault:\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tCWLog(\"Binding Configuration Request Parsed\");\n\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "WTPBinding.h",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n\n#ifndef __CAPWAP_WTPBinding_HEADER__\n#define __CAPWAP_WTPBinding_HEADER__\n\ntypedef struct {\n\tunsigned char radioID;\n\tWTPQosValues qosValues[NUM_QOS_PROFILES];\n} RadioQosValues;\n\ntypedef struct {\n\tint qosCount;\n\tRadioQosValues *radioQosValues;\n} CWBindingConfigurationRequestValues;\n\ntypedef struct {\n\tint qosCount;\n\tRadioQosValues *radioQosValues;\n} CWBindingConfigurationUpdateRequestValues;\n\n/****************************************************\n * 2009 Updates:                                    *\n *              New Structure for mananagement of   *\n *              OFDM Message Element                *\n ****************************************************/\n\ntypedef struct {\n\tunsigned char radioID;\n\tOFDMControlValues *radioOFDMValues;\n} CWBindingConfigurationUpdateRequestValuesOFDM;\n\n/****************************************************\n * 2009 Updates:                                    *\n *              Definition of port number and type  *\n *              of commands of Frequency Server     *\n *              Manager (WTP side).                 *\n ****************************************************/\n\n#define FREQ_SERVER_ADDR \"127.0.0.1\"\n#define FREQ_SERVER_PORT 1236\n\nCWBool CWWTPInitBinding(int radioIndex);\nCWBool CWBindingSaveConfigureResponse(void *bindingValuesPtr, CWProtocolResultCode * resultCode);\nCWBool CWBindingSetQosValues(int qosCount, RadioQosValues * radioQosValues, CWProtocolResultCode * resultCode);\nCWBool CWBindingParseConfigurationUpdateRequest(unsigned char *msg, int len, void **valuesPtr);\nCWBool CWBindingParseConfigureResponse(unsigned char *msg, int len, void **valuesPtr);\n/****************************************************\n * 2009 Updates: (SaveConfiguration)                *\n *              Prototype Modification (int * added)*\n ****************************************************/\nCWBool CWBindingSaveConfigurationUpdateRequest(void *bindingValuesPtr, CWProtocolResultCode * resultCode,\n\t\t\t\t\t       int *updateRequestType);\n#endif\n"
  },
  {
    "path": "WTPConfigFile.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nconst char *CW_CONFIG_FILE = \"config.wtp\";\n\nCWBool CWConfigFileInitLib()\n{\n\n\tgConfigValuesCount = 9;\n\n\tCW_CREATE_ARRAY_ERR(gConfigValues, gConfigValuesCount, CWConfigValue,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tgConfigValues[0].type = CW_STRING_ARRAY;\n\tgConfigValues[0].code = \"<AC_ADDRESSES>\";\n\tgConfigValues[0].endCode = \"</AC_ADDRESSES>\";\n\tgConfigValues[0].value.str_array_value = NULL;\n\tgConfigValues[0].count = 0;\n\n\tgConfigValues[1].type = CW_INTEGER;\n\tgConfigValues[1].code = \"</WTP_FORCE_MTU>\";\n\tgConfigValues[1].value.int_value = 0;\n\n\tgConfigValues[2].type = CW_STRING;\n\tgConfigValues[2].code = \"</WTP_LEV3_PROTOCOL>\";\n\tgConfigValues[2].value.str_value = NULL;\n\n\tgConfigValues[3].type = CW_STRING;\n\tgConfigValues[3].code = \"</WTP_NAME>\";\n\tgConfigValues[3].value.str_value = NULL;\n\n\tgConfigValues[4].type = CW_STRING;\n\tgConfigValues[4].code = \"</WTP_LOCATION>\";\n\tgConfigValues[4].value.str_value = NULL;\n\n\tgConfigValues[5].type = CW_STRING;\n\tgConfigValues[5].code = \"</WTP_FORCE_AC_ADDRESS>\";\n\tgConfigValues[5].value.str_value = NULL;\n\n\tgConfigValues[6].type = CW_STRING;\n\tgConfigValues[6].code = \"</WTP_FORCE_SECURITY>\";\n\tgConfigValues[6].value.str_value = NULL;\n\n\tgConfigValues[7].type = CW_INTEGER;\n\tgConfigValues[7].code = \"</AC_LOG_FILE_ENABLE>\";\n\tgConfigValues[7].value.int_value = 0;\n\n\tgConfigValues[8].type = CW_INTEGER;\n\tgConfigValues[8].code = \"</AC_LOG_FILE_SIZE>\";\n\tgConfigValues[8].value.int_value = DEFAULT_LOG_SIZE;\n\n\treturn CW_TRUE;\n}\n\nCWBool CWConfigFileDestroyLib()\n{\n\tint i;\n\n\t// save the preferences we read\n\n\tCW_CREATE_ARRAY_ERR(gCWACAddresses, gConfigValues[0].count, char *,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < gConfigValues[0].count; i++) {\n\t\tCW_CREATE_STRING_FROM_STRING_ERR(gCWACAddresses[i], (gConfigValues[0].value.str_array_value)[i],\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\n\tgCWACCount = gConfigValues[0].count;\n\n#ifdef CW_DEBUGGING\n\tCW_PRINT_STRING_ARRAY(gCWACAddresses, gCWACCount);\n#endif\n\n\tgCWForceMTU = gConfigValues[1].value.int_value;\n\n\tif (gConfigValues[2].value.str_value != NULL && !strcmp(gConfigValues[2].value.str_value, \"IPv6\")) {\n\t\tgNetworkPreferredFamily = CW_IPv6;\n\t} else {\t\t// default\n\t\tgNetworkPreferredFamily = CW_IPv4;\n\t}\n\n\tif (gConfigValues[3].value.str_value != NULL) {\n\t\tCW_CREATE_STRING_FROM_STRING_ERR(gWTPName, (gConfigValues[3].value.str_value),\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\tif (gConfigValues[4].value.str_value != NULL) {\n\t\tCW_CREATE_STRING_FROM_STRING_ERR(gWTPLocation, (gConfigValues[4].value.str_value),\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\tif (gConfigValues[5].value.str_value != NULL) {\n\t\tCW_CREATE_STRING_FROM_STRING_ERR(gWTPForceACAddress, (gConfigValues[5].value.str_value),\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\n\tif (gConfigValues[6].value.str_value != NULL && !strcmp(gConfigValues[6].value.str_value, \"PRESHARED\")) {\n\t\tgWTPForceSecurity = CW_PRESHARED;\n\t} else {\t\t// default\n\t\tgWTPForceSecurity = CW_X509_CERTIFICATE;\n\t}\n\n\tfor (i = 0; i < gConfigValuesCount; i++) {\n\t\tif (gConfigValues[i].type == CW_STRING) {\n\t\t\tCW_FREE_OBJECT(gConfigValues[i].value.str_value);\n\t\t} else if (gConfigValues[i].type == CW_STRING_ARRAY) {\n\t\t\tCW_FREE_OBJECTS_ARRAY((gConfigValues[i].value.str_array_value), gConfigValues[i].count);\n\t\t}\n\t}\n\n\tgEnabledLog = gConfigValues[7].value.int_value;\n\tgMaxLogFileSize = gConfigValues[8].value.int_value;\n\n\tCW_FREE_OBJECT(gConfigValues);\n\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "WTPConfigureState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/* void CWWTPResponseTimerExpired(void *arg, CWTimerID id); */\nCWBool CWAssembleConfigureRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t  int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList);\n\nCWBool CWParseConfigureResponseMessage(unsigned char *msg, int len, int seqNum, CWProtocolConfigureResponseValues * valuesPtr);\n\nCWBool CWSaveConfigureResponseMessage(CWProtocolConfigureResponseValues * configureResponse);\n\n/*_________________________________________________________*/\n/*  *******************___FUNCTIONS___*******************  */\n\n/*\n * Manage Configure State.\n */\nCWStateTransition CWWTPEnterConfigure()\n{\n\n\tint seqNum;\n\tCWProtocolConfigureResponseValues values;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"######### Configure State #########\");\n\n\t/* send Configure Request */\n\tseqNum = CWGetSeqNum();\n\n\tif (!CWErr(CWWTPSendAcknowledgedPacket(seqNum,\n\t\t\t\t\t       NULL,\n\t\t\t\t\t       CWAssembleConfigureRequest,\n\t\t\t\t\t       (void *)CWParseConfigureResponseMessage,\n\t\t\t\t\t       (void *)CWSaveConfigureResponseMessage, &values))) {\n\n\t\tCWNetworkCloseSocket(gWTPSocket);\n#ifndef CW_NO_DTLS\n\t\tCWSecurityDestroySession(gWTPSession);\n\t\tCWSecurityDestroyContext(gWTPSecurityContext);\n\t\tgWTPSecurityContext = NULL;\n\t\tgWTPSession = NULL;\n#endif\n\t\treturn CW_QUIT;\n\t}\n\n\treturn CW_ENTER_DATA_CHECK;\n}\n\n/*\nvoid CWWTPResponseTimerExpired(void *arg, CWTimerID id)\n{\n    CWLog(\"WTP Response Configure Timer Expired\");\n    CWNetworkCloseSocket(gWTPSocket);\n}\n*/\n\n/*\n * Send Configure Request on the active session.\n */\nCWBool CWAssembleConfigureRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t  int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemCount = 8;\n\tconst int msgElemBindingCount = 0;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWDebugLog(\"Assembling Configure Request...\");\n\n\t/* Assemble Message Elements */\n\tif ((!(CWAssembleMsgElemACName(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemACNameWithIndex(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemRadioAdminState(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemStatisticsTimer(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPRebootStatistics(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPRadioInformation(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemSupportedRates(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemMultiDomainCapability(&(msgElems[++k]))))) {\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\t/* error will be handled by the caller */\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CONFIGURE_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWDebugLog(\"Configure Request Assembled\");\n\treturn CW_TRUE;\n}\n\nCWBool CWParseConfigureResponseMessage(unsigned char *msg, int len, int seqNum, CWProtocolConfigureResponseValues * valuesPtr)\n{\n\n\tCWControlHeaderValues controlVal;\n\tCWProtocolMessage completeMsg;\n\tCWBool bindingMsgElemFound = CW_FALSE;\n\tint offsetTillMessages;\n\tint i = 0;\n\tint j = 0;\n\n\tif (msg == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Parsing Configure Response...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tvaluesPtr->echoRequestTimer = 0;\n\tvaluesPtr->radioOperationalInfoCount = 0;\n\tvaluesPtr->radiosDecryptErrorPeriod.radiosCount = 0;\n\tvaluesPtr->bindingValues = NULL;\n\tvaluesPtr->ACIPv4ListInfo.ACIPv4ListCount = 0;\n\tvaluesPtr->ACIPv4ListInfo.ACIPv4List = NULL;\n\tvaluesPtr->ACIPv6ListInfo.ACIPv6ListCount = 0;\n\tvaluesPtr->ACIPv6ListInfo.ACIPv6List = NULL;\n\n\t/* error will be handled by the caller */\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\treturn CW_FALSE;\n\n\t/* different type */\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_CONFIGURE_RESPONSE)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Configure Response as Expected\");\n\n\tif (controlVal.seqNum != seqNum)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Different Sequence Number\");\n\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\toffsetTillMessages = completeMsg.offset;\n\n\t/* parse message elements */\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\t\tunsigned short int type = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int len = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\t\t/* CWDebugLog(\"Parsing Message Element: %u, len: %u\", type, len); */\n\n\t\tif (CWBindingCheckType(type)) {\n\t\t\tbindingMsgElemFound = CW_TRUE;\n\t\t\tcompleteMsg.offset += len;\n\t\t\tcontinue;\n\t\t}\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_AC_IPV4_LIST_CW_TYPE:\n\t\t\tif (!(CWParseACIPv4List(&completeMsg, len, &(valuesPtr->ACIPv4ListInfo))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_AC_IPV6_LIST_CW_TYPE:\n\t\t\tif (!(CWParseACIPv6List(&completeMsg, len, &(valuesPtr->ACIPv6ListInfo))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_TIMERS_CW_TYPE:\n\t\t\tif (!(CWParseCWTimers(&completeMsg, len, valuesPtr)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE:\n\t\t\t/*\n\t\t\t * just count how many radios we have, so we\n\t\t\t * can allocate the array\n\t\t\t */\n\t\t\tvaluesPtr->radioOperationalInfoCount++;\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_PERIOD_CW_TYPE:\n\t\t\tvaluesPtr->radiosDecryptErrorPeriod.radiosCount++;\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_IDLE_TIMEOUT_CW_TYPE:\n\t\t\tif (!(CWParseIdleTimeout(&completeMsg, len, valuesPtr)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_FALLBACK_CW_TYPE:\n\t\t\tif (!(CWParseWTPFallback(&completeMsg, len, valuesPtr)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCW_CREATE_ARRAY_ERR((*valuesPtr).radioOperationalInfo,\n\t\t\t    (*valuesPtr).radioOperationalInfoCount,\n\t\t\t    CWRadioOperationalInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCW_CREATE_ARRAY_ERR((*valuesPtr).radiosDecryptErrorPeriod.radios,\n\t\t\t    (*valuesPtr).radiosDecryptErrorPeriod.radiosCount,\n\t\t\t    WTPDecryptErrorReportValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tcompleteMsg.offset = offsetTillMessages;\n\n\twhile (completeMsg.offset - offsetTillMessages < controlVal.msgElemsLen) {\n\t\tunsigned short int type = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int len = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseWTPRadioOperationalState(&completeMsg,\n\t\t\t\t\t\t\t      len, &(valuesPtr->radioOperationalInfo[i]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\ti++;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_PERIOD_CW_TYPE:\n\t\t\tif (!(CWParseDecryptErrorReportPeriod(&completeMsg,\n\t\t\t\t\t\t\t      len, &(valuesPtr->radiosDecryptErrorPeriod.radios[j]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tj++;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (bindingMsgElemFound) {\n\t\tif (!CWBindingParseConfigureResponse(msg + offsetTillMessages,\n\t\t\t\t\t\t     len - offsetTillMessages, &(valuesPtr->bindingValues))) {\n\t\t\treturn CW_FALSE;\n\t\t}\n\t}\n\n\tCWDebugLog(\"Configure Response Parsed\");\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveConfigureResponseMessage(CWProtocolConfigureResponseValues * configureResponse)\n{\n\n\tif (configureResponse == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\tif (gACInfoPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, NULL);\n\n\tCWDebugLog(\"Saving Configure Response...\");\n\tCWDebugLog(\"###A\");\n\tCWDebugLog(\"###Count:%d\", (configureResponse->ACIPv4ListInfo).ACIPv4ListCount);\n\tif ((gACInfoPtr->ACIPv4ListInfo).ACIPv4List == NULL) {\n\n\t\tCWDebugLog(\"###NULL\");\n\t}\n\n\tif ((configureResponse->ACIPv4ListInfo).ACIPv4ListCount > 0) {\n\n\t\t//CW_FREE_OBJECT((gACInfoPtr->ACIPv4ListInfo).ACIPv4List);\n\t\t(gACInfoPtr->ACIPv4ListInfo).ACIPv4ListCount = (configureResponse->ACIPv4ListInfo).ACIPv4ListCount;\n\t\t(gACInfoPtr->ACIPv4ListInfo).ACIPv4List = (configureResponse->ACIPv4ListInfo).ACIPv4List;\n\t}\n\n\tCWDebugLog(\"###B\");\n\n\tif ((configureResponse->ACIPv6ListInfo).ACIPv6ListCount > 0) {\n\n\t\t//CW_FREE_OBJECT((gACInfoPtr->ACIPv6ListInfo).ACIPv6List);\n\t\t(gACInfoPtr->ACIPv6ListInfo).ACIPv6ListCount = (configureResponse->ACIPv6ListInfo).ACIPv6ListCount;\n\t\t(gACInfoPtr->ACIPv6ListInfo).ACIPv6List = (configureResponse->ACIPv6ListInfo).ACIPv6List;\n\t}\n\n\tif (configureResponse->bindingValues != NULL) {\n\n\t\tCWProtocolResultCode resultCode;\n\n\t\tif (!CWBindingSaveConfigureResponse(configureResponse->bindingValues, &resultCode)) {\n\n\t\t\tCW_FREE_OBJECT(configureResponse->bindingValues);\n\t\t\treturn CW_FALSE;\n\t\t}\n\t}\n\n\tif (configureResponse->echoRequestTimer > 0) {\n\n\t\tgEchoInterval = configureResponse->echoRequestTimer;\n\t}\n\n\t/*\n\t   \"\"need to be added\"\"\n\n\t   int discoveryTimer;\n\t   int radioOperationalInfoCount;\n\t   CWRadioOperationalInfoValues *radioOperationalInfo;\n\t   WTPDecryptErrorReport radiosDecryptErrorPeriod;\n\t   int idleTimeout;\n\t   int fallback;\n\t */\n\n\t/*\n\t * It is not clear to me what the original developers intended to\n\t * accomplish. One thing's for sure: radioOperationalInfo, radiosDecryptErrorPeriod.radios,\n\t * and bidingValues get allocated and are never freed,\n\t * so we do it here...\n\t *\n\t * BUGs ML02-ML04-ML05\n\t * 16/10/2009 - Donato Capitella\n\t */\n\t//CW_FREE_OBJECT(configureResponse->radioOperationalInfo);\n\t//CW_FREE_OBJECT(configureResponse->radiosDecryptErrorPeriod.radios);\n\t//CW_FREE_OBJECT(configureResponse->bindingValues);\n\n\tCWDebugLog(\"Configure Response Saved\");\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "WTPDataCheckState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool CWAssembleChangeStateEventRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList);\n\nCWBool CWParseChangeStateEventResponseMessage(unsigned char *msg, int len, int seqNum, void *values);\n\nCWBool CWSaveChangeStateEventResponseMessage(void *changeStateEventResp);\n\nCWStateTransition CWWTPEnterDataCheck()\n{\n\n\tint seqNum;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"######### Data Check State #########\");\n\n\tCWLog(\"\\n\");\n\tCWLog(\"#________ Change State Event (Data Check) ________#\");\n\n\t/* Send Change State Event Request */\n\tseqNum = CWGetSeqNum();\n\n\tif (!CWErr(CWStartHeartbeatTimer())) {\n\t\treturn CW_ENTER_RESET;\n\t}\n\n\tif (!CWErr(CWWTPSendAcknowledgedPacket(seqNum,\n\t\t\t\t\t       NULL,\n\t\t\t\t\t       CWAssembleChangeStateEventRequest,\n\t\t\t\t\t       CWParseChangeStateEventResponseMessage,\n\t\t\t\t\t       CWSaveChangeStateEventResponseMessage, NULL))) {\n\t\treturn CW_ENTER_RESET;\n\t}\n\n\tif (!CWErr(CWStopHeartbeatTimer())) {\n\n\t\treturn CW_ENTER_RESET;\n\t}\n\n\treturn CW_ENTER_RUN;\n}\n\nCWBool CWAssembleChangeStateEventRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemCount = 2;\n\tint msgElemBindingCount = 0;\n\tint resultCode = CW_PROTOCOL_SUCCESS;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWLog(\"Assembling Change State Event Request...\");\n\n\t/* Assemble Message Elements */\n\tif (!(CWAssembleMsgElemRadioOperationalState(-1, &(msgElems[++k]))) ||\n\t    !(CWAssembleMsgElemResultCode(&(msgElems[++k]), resultCode))) {\n\n\t\tint i;\n\n\t\tfor (i = 0; i <= k; i++) {\n\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\t/* error will be handled by the caller */\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"Change State Event Request Assembled\");\n\treturn CW_TRUE;\n}\n\nCWBool CWParseChangeStateEventResponseMessage(unsigned char *msg, int len, int seqNum, void *values)\n{\n\n\tCWControlHeaderValues controlVal;\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing Change State Event Response...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\t/* error will be handled by the caller */\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\treturn CW_FALSE;\n\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_RESPONSE)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Change State Event Response as Expected\");\n\n\tif (controlVal.seqNum != seqNum)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Different Sequence Number\");\n\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\tif (controlVal.msgElemsLen != 0)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t\t    \"Change State Event Response must carry no message elements\");\n\n\tCWLog(\"Change State Event Response Parsed\");\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveChangeStateEventResponseMessage(void *changeStateEventResp)\n{\n\tCWDebugLog(\"Saving Change State Event Response...\");\n\tCWDebugLog(\"Change State Event Response Saved\");\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "WTPDiscoveryState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/*________________________________________________________________*/\n/*  *******************___CAPWAP VARIABLES___*******************  */\nint gCWMaxDiscoveries = 10;\n\n/*_________________________________________________________*/\n/*  *******************___VARIABLES___*******************  */\n\nint gCWDiscoveryCount;\n#ifdef CW_DEBUGGING\nint gCWDiscoveryInterval = 3;\t//5;\nint gCWMaxDiscoveryInterval = 4;\t//20;\n#else\nint gCWDiscoveryInterval = 5;\nint gCWMaxDiscoveryInterval = 20;\n#endif\n\n/*_____________________________________________________*/\n/*  *******************___MACRO___*******************  */\n#define CWWTPFoundAnAC()    (gACInfoPtr != NULL /*&& gACInfoPtr->preferredAddress.ss_family != AF_UNSPEC*/)\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\nCWBool CWReceiveDiscoveryResponse();\nvoid CWWTPEvaluateAC(CWACInfoValues * ACInfoPtr);\nCWBool CWReadResponses();\nCWBool CWAssembleDiscoveryRequest(CWProtocolMessage ** messagesPtr, int seqNum);\nCWBool CWParseDiscoveryResponseMessage(unsigned char *msg, int len, int *seqNumPtr, CWACInfoValues * ACInfoPtr);\n\n/*_________________________________________________________*/\n/*  *******************___FUNCTIONS___*******************  */\n\n/*\n * Manage Discovery State\n */\nCWStateTransition CWWTPEnterDiscovery()\n{\n\tint i;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"######### Discovery State #########\");\n\n\t/* reset Discovery state */\n\tgCWDiscoveryCount = 0;\n\tCWNetworkCloseSocket(gWTPSocket);\n\tif (!CWErr(CWNetworkInitSocketClient(&gWTPSocket, NULL))) {\n\t\treturn CW_QUIT;\n\t}\n\n\t/*\n\t * note: gCWACList can be freed and reallocated (reading from config file)\n\t * at each transition to the discovery state to save memory space\n\t */\n\tfor (i = 0; i < gCWACCount; i++)\n\t\tgCWACList[i].received = CW_FALSE;\n\n\t/* wait a random time */\n\tsleep(CWRandomIntInRange(gCWDiscoveryInterval, gCWMaxDiscoveryInterval));\n\n\tCW_REPEAT_FOREVER {\n\t\tCWBool sentSomething = CW_FALSE;\n\n\t\t/* we get no responses for a very long time */\n\t\tif (gCWDiscoveryCount == gCWMaxDiscoveries)\n\t\t\treturn CW_ENTER_SULKING;\n\n\t\t/* send Requests to one or more ACs */\n\t\tfor (i = 0; i < gCWACCount; i++) {\n\n\t\t\t/* if this AC hasn't responded to us... */\n\t\t\tif (!(gCWACList[i].received)) {\n\t\t\t\t/* ...send a Discovery Request */\n\n\t\t\t\tCWProtocolMessage *msgPtr = NULL;\n\n\t\t\t\t/* get sequence number (and increase it) */\n\t\t\t\tgCWACList[i].seqNum = CWGetSeqNum();\n\n\t\t\t\tif (!CWErr(CWAssembleDiscoveryRequest(&msgPtr, gCWACList[i].seqNum))) {\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\n\t\t\t\tCW_CREATE_OBJECT_ERR(gACInfoPtr, CWACInfoValues, return CW_QUIT;\n\t\t\t\t    );\n\n\t\t\t\tCWNetworkGetAddressForHost(gCWACList[i].address, &(gACInfoPtr->preferredAddress));\n\n\t\t\t\tCWUseSockNtop(&(gACInfoPtr->preferredAddress), CWDebugLog(str);\n\t\t\t\t    );\n\n\t\t\t\t//j = CWErr(CWNetworkSendUnsafeUnconnected(gWTPSocket,\n\t\t\t\t//\t\t\t\t\t &(gACInfoPtr->preferredAddress),\n\t\t\t\t//\t\t\t\t\t (*msgPtr).msg, (*msgPtr).offset));\n\t\t\t\t/*\n\t\t\t\t * log eventual error and continue\n\t\t\t\t * CWUseSockNtop(&(gACInfoPtr->preferredAddress),\n\t\t\t\t *       CWLog(\"WTP sends Discovery Request to: %s\", str););\n\t\t\t\t */\n\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*msgPtr);\n\t\t\t\tCW_FREE_OBJECT(msgPtr);\n\t\t\t\tCW_FREE_OBJECT(gACInfoPtr);\n\n\t\t\t\t/*\n\t\t\t\t * we sent at least one Request in this loop\n\t\t\t\t * (even if we got an error sending it)\n\t\t\t\t */\n\t\t\t\tsentSomething = CW_TRUE;\n\t\t\t}\n\t\t}\n\n\t\t/* All AC sent the response (so we didn't send any request) */\n\t\tif (!sentSomething && CWWTPFoundAnAC())\n\t\t\tbreak;\n\n\t\tgCWDiscoveryCount++;\n\n\t\t/* wait for Responses */\n\t\tif (CWErr(CWReadResponses()) && CWWTPFoundAnAC()) {\n\t\t\t/* we read at least one valid Discovery Response */\n\t\t\tbreak;\n\t\t}\n\n\t\tCWLog(\"WTP Discovery-To-Discovery (%d)\", gCWDiscoveryCount);\n\t}\n\n\tCWLog(\"WTP Picks an AC\");\n\n\t/* crit error: we should have received at least one Discovery Response */\n\tif (!CWWTPFoundAnAC()) {\n\t\tCWLog(\"No Discovery response Received\");\n\t\treturn CW_ENTER_DISCOVERY;\n\t}\n\n\t/* if the AC is multi homed, we select our favorite AC's interface */\n\tCWWTPPickACInterface();\n\n\tCWUseSockNtop(&(gACInfoPtr->preferredAddress),\n\t\t      CWLog(\"Preferred AC: \\\"%s\\\", at address: %s\", gACInfoPtr->name, str);\n\t    );\n\n\treturn CW_ENTER_JOIN;\n}\n\n/*\n * Wait DiscoveryInterval time while receiving Discovery Responses.\n */\nCWBool CWReadResponses()\n{\n\n\tCWBool result = CW_FALSE;\n\n\tstruct timeval timeout, before, after, delta, newTimeout;\n\n\ttimeout.tv_sec = newTimeout.tv_sec = gCWDiscoveryInterval;\n\ttimeout.tv_usec = newTimeout.tv_usec = 0;\n\n\tgettimeofday(&before, NULL);\n\n\tCW_REPEAT_FOREVER {\n\t\t/* check if something is available to read until newTimeout */\n\t\tif (CWNetworkTimedPollRead(gWTPSocket, &newTimeout)) {\n\t\t\t/* success\n\t\t\t * if there was no error, raise a \"success error\", so we can easily handle\n\t\t\t * all the cases in the switch\n\t\t\t */\n\t\t\tCWErrorRaise(CW_ERROR_SUCCESS, NULL);\n\t\t}\n\n\t\tswitch (CWErrorGetLastErrorCode()) {\n\t\tcase CW_ERROR_TIME_EXPIRED:\n\t\t\tgoto cw_time_over;\n\t\t\tbreak;\n\n\t\tcase CW_ERROR_SUCCESS:\n\t\t\tresult = CWReceiveDiscoveryResponse();\n\t\tcase CW_ERROR_INTERRUPTED:\n\t\t\t/*\n\t\t\t * something to read OR interrupted by the system\n\t\t\t * wait for the remaining time (NetworkPoll will be recalled with the remaining time)\n\t\t\t */\n\t\t\tgettimeofday(&after, NULL);\n\n\t\t\tCWTimevalSubtract(&delta, &after, &before);\n\t\t\tif (CWTimevalSubtract(&newTimeout, &timeout, &delta) == 1) {\n\t\t\t\t/* negative delta: time is over */\n\t\t\t\tgoto cw_time_over;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tCWErrorHandleLast();\n\t\t\tgoto cw_error;\n\t\t\tbreak;\n\t\t}\n\t}\n cw_time_over:\n\t/* time is over */\n\tCWDebugLog(\"Timer expired during receive\");\n cw_error:\n\treturn result;\n}\n\n/*\n * Gets a datagram from network that should be a Discovery Response.\n */\nCWBool CWReceiveDiscoveryResponse()\n{\n\tunsigned char buf[CW_BUFFER_SIZE];\n\tint i;\n\tCWNetworkLev4Address addr;\n\tCWACInfoValues *ACInfoPtr;\n\tint seqNum;\n\tint readBytes;\n\n\t/* receive the datagram */\n\tif (!CWErr(CWNetworkReceiveUnsafe(gWTPSocket, buf, CW_BUFFER_SIZE - 1, 0, &addr, &readBytes))) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCW_CREATE_OBJECT_ERR(ACInfoPtr, CWACInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/* check if it is a valid Discovery Response */\n\tif (!CWErr(CWParseDiscoveryResponseMessage(buf, readBytes, &seqNum, ACInfoPtr))) {\n\n\t\tCW_FREE_OBJECT(ACInfoPtr);\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Received something different from a\\\n                     Discovery Response while in Discovery State\");\n\t}\n\n\tCW_COPY_NET_ADDR_PTR(&(ACInfoPtr->incomingAddress), &(addr));\n\n\t/* see if this AC is better than the one we have stored */\n\tCWWTPEvaluateAC(ACInfoPtr);\n\n\tCWLog(\"WTP Receives Discovery Response\");\n\n\t/* check if the sequence number we got is correct */\n\tfor (i = 0; i < gCWACCount; i++) {\n\n\t\tif (gCWACList[i].seqNum == seqNum) {\n\n\t\t\tCWUseSockNtop(&addr, CWLog(\"Discovery Response from:%s\", str);\n\t\t\t    );\n\t\t\t/* we received response from this address */\n\t\t\tgCWACList[i].received = CW_TRUE;\n\n\t\t\treturn CW_TRUE;\n\t\t}\n\t}\n\n\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Sequence Number of Response doesn't macth Request\");\n}\n\nvoid CWWTPEvaluateAC(CWACInfoValues * ACInfoPtr)\n{\n\n\tif (ACInfoPtr == NULL)\n\t\treturn;\n\n\tif (gACInfoPtr == NULL) {\n\t\t/*\n\t\t * this is the first AC we evaluate: so\n\t\t *  it's the best AC we examined so far\n\t\t */\n\t\tgACInfoPtr = ACInfoPtr;\n\n\t} else {\n\n\t\tCW_FREE_OBJECT(ACInfoPtr);\n\t}\n\t/*\n\t * ... note: we can add our favourite algorithm to pick the best AC.\n\t * We can also consider to remember all the Discovery Responses we\n\t * received and not just the best.\n\t */\n}\n\n/*\n * Pick one interface of the AC (easy if there is just one interface). The\n * current algorithm just pick the Ac with less WTP communicating with it. If\n * the addresses returned by the AC in the Discovery Response don't include the\n * address of the sender of the Discovery Response, we ignore the address in\n * the Response and use the one of the sender (maybe the AC sees garbage\n * address, i.e. it is behind a NAT).\n */\nvoid CWWTPPickACInterface()\n{\n\tint i, min;\n\tCWBool foundIncoming = CW_FALSE;\n\tif (gACInfoPtr == NULL)\n\t\treturn;\n\n\tgACInfoPtr->preferredAddress.ss_family = AF_UNSPEC;\n\n\tif (gNetworkPreferredFamily == CW_IPv6) {\n\t\tgoto cw_pick_IPv6;\n\t}\n\n cw_pick_IPv4:\n\tif (gACInfoPtr->IPv4Addresses == NULL || gACInfoPtr->IPv4AddressesCount <= 0)\n\t\treturn;\n\n\tmin = gACInfoPtr->IPv4Addresses[0].WTPCount;\n\n\tCW_COPY_NET_ADDR_PTR(&(gACInfoPtr->preferredAddress), &(gACInfoPtr->IPv4Addresses[0].addr));\n\n\tfor (i = 1; i < gACInfoPtr->IPv4AddressesCount; i++) {\n\n\t\tif (!sock_cmp_addr((struct sockaddr *)&(gACInfoPtr->IPv4Addresses[i]),\n\t\t\t\t   (struct sockaddr *)&(gACInfoPtr->incomingAddress), sizeof(struct sockaddr_in)))\n\t\t\tfoundIncoming = CW_TRUE;\n\n\t\tif (gACInfoPtr->IPv4Addresses[i].WTPCount < min) {\n\n\t\t\tmin = gACInfoPtr->IPv4Addresses[i].WTPCount;\n\t\t\tCW_COPY_NET_ADDR_PTR(&(gACInfoPtr->preferredAddress), &(gACInfoPtr->IPv4Addresses[i].addr));\n\t\t}\n\t}\n\n\tif (!foundIncoming) {\n\t\t/*\n\t\t * If the addresses returned by the AC in the Discovery\n\t\t * Response don't include the address of the sender of the\n\t\t * Discovery Response, we ignore the address in the Response\n\t\t * and use the one of the sender (maybe the AC sees garbage\n\t\t * address, i.e. it is behind a NAT).\n\t\t */\n\t\tCW_COPY_NET_ADDR_PTR(&(gACInfoPtr->preferredAddress), &(gACInfoPtr->incomingAddress));\n\t}\n\treturn;\n\n cw_pick_IPv6:\n\t/* CWDebugLog(\"Pick IPv6\"); */\n\tif (gACInfoPtr->IPv6Addresses == NULL || gACInfoPtr->IPv6AddressesCount <= 0)\n\t\tgoto cw_pick_IPv4;\n\n\tmin = gACInfoPtr->IPv6Addresses[0].WTPCount;\n\tCW_COPY_NET_ADDR_PTR(&(gACInfoPtr->preferredAddress), &(gACInfoPtr->IPv6Addresses[0].addr));\n\n\tfor (i = 1; i < gACInfoPtr->IPv6AddressesCount; i++) {\n\n\t\t/*\n\t\t * if(!sock_cmp_addr(&(gACInfoPtr->IPv6Addresses[i]),\n\t\t *           &(gACInfoPtr->incomingAddress),\n\t\t *           sizeof(struct sockaddr_in6)))\n\t\t *\n\t\t *  foundIncoming = CW_TRUE;\n\t\t */\n\n\t\tif (gACInfoPtr->IPv6Addresses[i].WTPCount < min) {\n\t\t\tmin = gACInfoPtr->IPv6Addresses[i].WTPCount;\n\t\t\tCW_COPY_NET_ADDR_PTR(&(gACInfoPtr->preferredAddress), &(gACInfoPtr->IPv6Addresses[i].addr));\n\t\t}\n\t}\n\t/*\n\t   if(!foundIncoming) {\n\t   CW_COPY_NET_ADDR_PTR(&(gACInfoPtr->preferredAddress),\n\t   &(gACInfoPtr->incomingAddress));\n\t   }\n\t */\n\treturn;\n}\n\nCWBool CWAssembleDiscoveryRequest(CWProtocolMessage ** messagesPtr, int seqNum)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 6;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\tint k = -1;\n\tint fragmentsNum;\n\n\tif (messagesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t/* Assemble Message Elements */\n\n\tif ((!(CWAssembleMsgElemDiscoveryType(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPBoardData(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPDescriptor(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPFrameTunnelMode(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPMACType(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPRadioInformation(&(msgElems[++k]))))\n\t    ) {\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\t/* error will be handled by the caller */\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CWAssembleMessage(messagesPtr,\n\t\t\t\t &fragmentsNum,\n\t\t\t\t 0,\n\t\t\t\t seqNum,\n\t\t\t\t CW_MSG_TYPE_VALUE_DISCOVERY_REQUEST,\n\t\t\t\t msgElems, msgElemCount, msgElemsBinding, msgElemBindingCount);\n}\n\n/*\n *  Parse Discovery Response and return informations in *ACInfoPtr.\n */\nCWBool CWParseDiscoveryResponseMessage(unsigned char *msg, int len, int *seqNumPtr, CWACInfoValues * ACInfoPtr)\n{\n\n\tCWControlHeaderValues controlVal;\n\tCWProtocolTransportHeaderValues transportVal;\n\tint offsetTillMessages, i, j;\n\tchar tmp_ABGNTypes;\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL || seqNumPtr == NULL || ACInfoPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Parse Discovery Response\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tCWBool dataFlag = CW_FALSE;\n\t/* will be handled by the caller */\n\tif (!(CWParseTransportHeader(&completeMsg, &transportVal, &dataFlag, NULL)))\n\t\treturn CW_FALSE;\n\t/* will be handled by the caller */\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\treturn CW_FALSE;\n\n\t/* different type */\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_DISCOVERY_RESPONSE)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Discovery Response as Expected\");\n\n\t*seqNumPtr = controlVal.seqNum;\n\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\toffsetTillMessages = completeMsg.offset;\n\n\tACInfoPtr->IPv4AddressesCount = 0;\n\tACInfoPtr->IPv6AddressesCount = 0;\n\t/* parse message elements */\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\t\tunsigned short int type = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int len = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\t\tCWDebugLog(\"Parsing Message Element: %u, len: %u\", type, len);\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_AC_DESCRIPTOR_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseACDescriptor(&completeMsg, len, ACInfoPtr)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseWTPRadioInformation_FromAC(&completeMsg, len, &tmp_ABGNTypes)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_AC_NAME_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseACName(&completeMsg, len, &(ACInfoPtr->name))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV4_ADDRESS_CW_TYPE:\n\t\t\t/*\n\t\t\t * just count how many interfacess we have,\n\t\t\t * so we can allocate the array\n\t\t\t */\n\t\t\tACInfoPtr->IPv4AddressesCount++;\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV6_ADDRESS_CW_TYPE:\n\t\t\t/*\n\t\t\t * just count how many interfacess we have,\n\t\t\t * so we can allocate the array\n\t\t\t */\n\t\t\tACInfoPtr->IPv6AddressesCount++;\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\n\t\t/* CWDebugLog(\"bytes: %d/%d\",\n\t\t *        (completeMsg.offset-offsetTillMessages),\n\t\t *        controlVal.msgElemsLen);\n\t\t */\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\t/* actually read each interface info */\n\tCW_CREATE_ARRAY_ERR(ACInfoPtr->IPv4Addresses,\n\t\t\t    ACInfoPtr->IPv4AddressesCount,\n\t\t\t    CWProtocolIPv4NetworkInterface, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (ACInfoPtr->IPv6AddressesCount > 0) {\n\n\t\tCW_CREATE_ARRAY_ERR(ACInfoPtr->IPv6Addresses,\n\t\t\t\t    ACInfoPtr->IPv6AddressesCount,\n\t\t\t\t    CWProtocolIPv6NetworkInterface, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\n\ti = 0, j = 0;\n\n\tcompleteMsg.offset = offsetTillMessages;\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\n\t\tunsigned short int type = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int len = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV4_ADDRESS_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseCWControlIPv4Addresses(&completeMsg, len, &(ACInfoPtr->IPv4Addresses[i]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\ti++;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV6_ADDRESS_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseCWControlIPv6Addresses(&completeMsg, len, &(ACInfoPtr->IPv6Addresses[j]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tj++;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "WTPDriverInteraction.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define SIOCIWFIRSTPRIV         0x8BE0\n#define IEEE80211_IOCTL_SETWMMPARAMS    (SIOCIWFIRSTPRIV+4)\n#define IEEE80211_IOCTL_GETWMMPARAMS    (SIOCIWFIRSTPRIV+5)\n#define IEEE80211_WMMPARAMS_CWMIN   1\n#define IEEE80211_WMMPARAMS_CWMAX   2\n#define IEEE80211_WMMPARAMS_AIFS    3\n\n/**************************** mac80211 ****************************/\n\n/**************************** iwconfig ****************************/\n/*--------------------------- Frequency ---------------------------*/\nint set_freq(int sock, struct iwreq wrq, int value)\n{\n\twrq.u.freq.m = value;\t//in Ghz/10\n\twrq.u.freq.e = 1;\n\n\tif (ioctl(sock, SIOCSIWFREQ, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nFrequenza impostata a: %d\\n\", wrq.u.freq.m);\n\n\treturn 1;\n}\n\nint get_freq(int sock, struct iwreq *wrq)\n{\n\tif (ioctl(sock, SIOCGIWFREQ, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nFrequenza: %d\\n\", wrq->u.freq.m);\n\n\treturn 1;\n}\n\n/*--------------------------- Bit rate ---------------------------*/\nint set_bitrate(int sock, struct iwreq wrq, int value)\n{\n\twrq.u.bitrate.value = value;\n\twrq.u.bitrate.fixed = 1;\n\n\tif (ioctl(sock, SIOCSIWRATE, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nBit rate impostato a: %d\\n\", wrq.u.bitrate.value);\n\n\treturn 1;\n}\n\nint get_bitrate(int sock, struct iwreq *wrq)\n{\n\tif (ioctl(sock, SIOCGIWRATE, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nBit rate: %d\\n\", wrq->u.bitrate.value);\n\n\treturn 1;\n}\n\n/*--------------------------- RTS/CTS Threshold ---------------------------*/\nint set_rts_cts(int sock, struct iwreq wrq, int value)\n{\n\tif (value != 0) {\n\t\twrq.u.rts.value = value;\n\t} else {\n\t\twrq.u.rts.disabled = 1;\n\t}\n\n\tif (ioctl(sock, SIOCSIWRTS, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nRTS/CTS threshold impostato a: %d\\n\", wrq.u.rts.value);\n\n\treturn 1;\n}\n\nint get_rts_cts(int sock, struct iwreq *wrq)\n{\n\tif (ioctl(sock, SIOCGIWRTS, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tif (wrq->u.rts.disabled != 1) {\n\t\tprintf(\"\\nRTS/CTS threshold: %d\\n\", wrq->u.rts.value);\n\t} else {\n\t\tprintf(\"\\nRTS/CTS threshold off\\n\");\n\t}\n\n\treturn 1;\n}\n\n/*--------------------------- Fragmentation Threshold ---------------------------*/\nint set_frag(int sock, struct iwreq wrq, int value)\n{\n\tif (value != 0) {\n\t\twrq.u.frag.value = value;\n\t} else {\n\t\twrq.u.frag.disabled = 1;\n\t}\n\n\tif (ioctl(sock, SIOCSIWFRAG, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nFragmentation threshold impostato a: %d\\n\", wrq.u.frag.value);\n\n\treturn 1;\n}\n\nint get_frag(int sock, struct iwreq *wrq)\n{\n\tif (ioctl(sock, SIOCGIWFRAG, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tif (wrq->u.frag.disabled != 1) {\n\t\tprintf(\"\\nFragmentation threshold: %d\\n\", wrq->u.frag.value);\n\t} else {\n\t\tprintf(\"\\nFragmentation threshold off\\n\");\n\t}\n\n\treturn 1;\n}\n\n/*--------------------------- Transmit Power ---------------------------*/\nint set_txpower(int sock, struct iwreq wrq, int value)\n{\n\twrq.u.txpower.value = value;\n\twrq.u.txpower.fixed = 1;\n\n\tif (ioctl(sock, SIOCSIWTXPOW, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nTransmit power impostato a: %d\\n\", wrq.u.txpower.value);\n\n\treturn 1;\n}\n\nint get_txpower(int sock, struct iwreq *wrq)\n{\n\tif (ioctl(sock, SIOCGIWTXPOW, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tif (wrq->u.txpower.disabled != 1) {\n\t\tprintf(\"\\nTransmit power: %d\\n\", wrq->u.txpower.value);\n\t} else {\n\t\tprintf(\"\\nTransmit power off\\n\");\n\t}\n\n\treturn 1;\n}\n\n/**************************** iwpriv ****************************/\n/*--------------------------- CWMIN ---------------------------*/\nint set_cwmin(int sock, struct iwreq wrq, int acclass, int sta, int value)\n{\n\tint buffer[3];\n\n\twrq.u.mode = IEEE80211_WMMPARAMS_CWMIN;\n\tbuffer[0] = acclass;\n\tbuffer[1] = sta;\n\tbuffer[2] = value;\n\tmemcpy(wrq.u.name + sizeof(int), buffer, sizeof(buffer));\n\n\tif (ioctl(sock, IEEE80211_IOCTL_SETWMMPARAMS, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nCWMIN impostato a: %d\\n\", value);\n\n\treturn 1;\n}\n\nint get_cwmin(int sock, struct iwreq *wrq, int acclass, int sta)\n{\n\tint buffer[2];\n\n\twrq->u.mode = IEEE80211_WMMPARAMS_CWMIN;\n\tbuffer[0] = acclass;\n\tbuffer[1] = sta;\n\tmemcpy(wrq->u.name + sizeof(int), buffer, sizeof(buffer));\n\n\tif (ioctl(sock, IEEE80211_IOCTL_GETWMMPARAMS, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n//  printf(\"\\nCWMIN: %d\\n\", wrq->u.param.value);\n\n\treturn 1;\n}\n\n/*--------------------------- CWMAX ---------------------------*/\nint set_cwmax(int sock, struct iwreq wrq, int acclass, int sta, int value)\n{\n\tint buffer[3];\n\n\twrq.u.mode = IEEE80211_WMMPARAMS_CWMAX;\n\tbuffer[0] = acclass;\n\tbuffer[1] = sta;\n\tbuffer[2] = value;\n\tmemcpy(wrq.u.name + sizeof(int), buffer, sizeof(buffer));\n\n\tif (ioctl(sock, IEEE80211_IOCTL_SETWMMPARAMS, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nCWMAX impostato a: %d\\n\", value);\n\n\treturn 1;\n}\n\nint get_cwmax(int sock, struct iwreq *wrq, int acclass, int sta)\n{\n\tint buffer[2];\n\n\twrq->u.mode = IEEE80211_WMMPARAMS_CWMAX;\n\tbuffer[0] = acclass;\n\tbuffer[1] = sta;\n\tmemcpy(wrq->u.name + sizeof(int), buffer, sizeof(buffer));\n\n\tif (ioctl(sock, IEEE80211_IOCTL_GETWMMPARAMS, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\t//printf(\"\\nCWMAX: %d\\n\", wrq->u.param.value);\n\n\treturn 1;\n}\n\n/*--------------------------- AIFS ---------------------------*/\nint set_aifs(int sock, struct iwreq wrq, int acclass, int sta, int value)\n{\n\tint buffer[3];\n\n\twrq.u.mode = IEEE80211_WMMPARAMS_AIFS;\n\tbuffer[0] = acclass;\n\tbuffer[1] = sta;\n\tbuffer[2] = value;\n\tmemcpy(wrq.u.name + sizeof(int), buffer, sizeof(buffer));\n\n\tif (ioctl(sock, IEEE80211_IOCTL_SETWMMPARAMS, &wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\n\tprintf(\"\\nAIFS impostato a: %d\\n\", value);\n\n\treturn 1;\n}\n\nint get_aifs(int sock, struct iwreq *wrq, int acclass, int sta)\n{\n\tint buffer[2];\n\n\twrq->u.mode = IEEE80211_WMMPARAMS_AIFS;\n\tbuffer[0] = acclass;\n\tbuffer[1] = sta;\n\tmemcpy(wrq->u.name + sizeof(int), buffer, sizeof(buffer));\n\n\tif (ioctl(sock, IEEE80211_IOCTL_GETWMMPARAMS, wrq) < 0) {\n\t\tperror(\"Ioctl error\");\n\t\treturn (0);\n\t}\n\t//printf(\"\\nAIFS: %d\\n\", wrq->u.param.value);\n\n\treturn 1;\n}\n"
  },
  {
    "path": "WTPFrameReceive.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"WTPFrameReceive.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define EXIT_FRAME_THREAD(sock) CWLog(\"ERROR Handling Frames: application will be closed!\");        \\\n                close(sock);                                \\\n                exit(1);\n\nint getMacAddr(int sock, char *interface, unsigned char *macAddr)\n{\n\n\tstruct ifreq ethreq;\n\tint i;\n\n\tmemset(&ethreq, 0, sizeof(ethreq));\n\tstrncpy(ethreq.ifr_name, interface, IFNAMSIZ);\n\tif (ioctl(sock, SIOCGIFHWADDR, &ethreq) == -1) {\n\t\treturn 0;\n\t}\n\n\tfor (i = 0; i < MAC_ADDR_LEN; i++) {\n\t\tmacAddr[i] = (unsigned char)ethreq.ifr_hwaddr.sa_data[i];\n\t}\n\tCWDebugLog(\"\\n\");\n\n\treturn 1;\n}\n\nint extractFrameInfo(char *buffer, char *RSSI, char *SNR, int *dataRate)\n{\n\tint signal, noise;\n\n\t*RSSI = buffer[RSSI_BYTE] - ATHEROS_CONV_VALUE;\t//RSSI in dBm\n\n\tsignal = buffer[SIGNAL_BYTE] - ATHEROS_CONV_VALUE;\n\tnoise = buffer[NOISE_BYTE];\n\t*SNR = (char)signal - noise;\t//RSN in dB\n\n\t*dataRate = (buffer[DATARATE_BYTE] / 2) * 10;\t//Data rate in Mbps*10\n\treturn 1;\n}\n\nint extractFrame(CWProtocolMessage ** frame, unsigned char *buffer, int len)\t//len: frame length including prism header\n{\n\n\tCW_CREATE_OBJECT_ERR(*frame, CWProtocolMessage, return 0;\n\t    );\n\tCWProtocolMessage *auxPtr = *frame;\n\tCW_CREATE_PROTOCOL_MESSAGE(*auxPtr, len - PRISMH_LEN, return 0;\n\t    );\n\tmemcpy(auxPtr->msg, buffer + PRISMH_LEN, len - PRISMH_LEN);\n\tauxPtr->offset = len - PRISMH_LEN;\n\treturn 1;\n}\n\nint extract802_3_Frame(CWProtocolMessage ** frame, unsigned char *buffer, int len)\n{\n\tCW_CREATE_OBJECT_ERR(*frame, CWProtocolMessage, return 0;\n\t    );\n\tCWProtocolMessage *auxPtr = *frame;\n\tCW_CREATE_PROTOCOL_MESSAGE(*auxPtr, len, return 0;\n\t    );\n\tmemcpy(auxPtr->msg, buffer, len);\n\tauxPtr->offset = len;\n\treturn 1;\n}\n\nint extractAddr(unsigned char *destAddr, unsigned char *sourceAddr, char *frame)\n{\n\tmemset(destAddr, 0, MAC_ADDR_LEN);\n\tmemset(sourceAddr, 0, MAC_ADDR_LEN);\n\tmemcpy(destAddr, frame + DEST_ADDR_START, MAC_ADDR_LEN);\n\tmemcpy(sourceAddr, frame + SOURCE_ADDR_START, MAC_ADDR_LEN);\n\n\treturn 1;\n}\n\nint macAddrCmp(unsigned char *addr1, unsigned char *addr2)\n{\n\tint i, ok = 1;\n\n\t/*  CWDebugLog(\"Address 1:\");\n\t   for (i=0; i<MAC_ADDR_LEN; i++)\n\t   {\n\t   CWDebugLog(\"%02x \", addr1[i]);\n\t   }\n\n\t   CWDebugLog(\"\\nAddress 2:\");\n\t   for (i=0; i<MAC_ADDR_LEN; i++)\n\t   {\n\t   CWDebugLog(\"%02x \", addr2[i]);\n\t   }\n\t   CWDebugLog(\"\\n\"); */\n\n\tfor (i = 0; i < MAC_ADDR_LEN; i++) {\n\t\tif (addr1[i] != addr2[i]) {\n\t\t\tok = 0;\n\t\t}\n\t}\n\n\tif (ok == 1) {\n\t\tCWDebugLog(\"MAC Address test: OK\\n\");\n\t} else {\n\t\tCWDebugLog(\"MAC Address test: Failed\\n\");\n\t}\n\n\treturn ok;\n}\n\nint gRawSock;\nextern int wtpInRunState;\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveFrame(void *arg)\n{\n\n\tconst unsigned char VERSION_MASK = 3, TYPE_MASK = 12, SUBTYPE_MASK = 240;\n\tconst unsigned char MANAGEMENT_TYPE = 0, CONTROL_TYPE = 4, DATA_TYPE = 8;\n\tint n;\n\tunsigned char buffer[2048];\n\tunsigned char macAddr[MAC_ADDR_LEN];\n\tunsigned char destAddr[MAC_ADDR_LEN];\n\tunsigned char sourceAddr[MAC_ADDR_LEN];\n\tunsigned char byte0, version = 0, type = 0, subtype = 0;\n\tstruct sockaddr_ll addr;\n\tCWBindingTransportHeaderValues *bindingValuesPtr = NULL;\n\tCWProtocolMessage *frame = NULL;\n\tCWBindingDataListElement *listElement = NULL;\n#ifdef PROMODE_ON\n\tstruct ifreq ethreq;\n#endif\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n\tif ((gRawSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {\n\t\tCWDebugLog(\"THR FRAME: Error creating socket\");\n\t\tCWExitThread();\n\t}\n\n\t/*\n\t * BUG - UMR02\n\t * It is better to zero the sockaddr structure before\n\t * passing it to the kernel.\n\t *\n\t * 19/10/2009 - Donato Capitella\n\t */\n\tmemset(&addr, 0, sizeof(addr));\n\n\taddr.sll_family = AF_PACKET;\n\taddr.sll_protocol = htons(ETH_P_ALL);\n\taddr.sll_pkttype = PACKET_HOST;\n\taddr.sll_ifindex = if_nametoindex(gInterfaceName);\n\n\tif ((bind(gRawSock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {\n\t\tCWDebugLog(\"THR FRAME: Error binding socket\");\n\t\tCWExitThread();\n\t}\n\n\tif (!getMacAddr(gRawSock, gInterfaceName, macAddr)) {\n\t\tCWDebugLog(\"THR FRAME: Ioctl error\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n#ifdef PROMODE_ON\n\t/* Set the network card in promiscuos mode */\n\tstrncpy(ethreq.ifr_name, gInterfaceName, IFNAMSIZ);\n\tif (ioctl(gRawSock, SIOCGIFFLAGS, &ethreq) == -1) {\n\t\tCWDebugLog(\"THR FRAME: Error ioctl\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n\tethreq.ifr_flags |= IFF_PROMISC;\n\tif (ioctl(gRawSock, SIOCSIFFLAGS, &ethreq) == -1) {\n\t\tCWDebugLog(\"THR FRAME: Error ioctl\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n#endif\n#ifdef FILTER_ON\n\t/* Attach the filter to the socket */\n\tif (setsockopt(gRawSock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)) < 0) {\n\t\tCWDebugLog(\"THR FRAME: Error attaching filter\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n#endif\n\n\tCW_REPEAT_FOREVER {\n\t\tn = recvfrom(gRawSock, buffer, sizeof(buffer), 0, NULL, NULL);\n\n\t\tif (!wtpInRunState) {\n\t\t\tCWLog(\"frame packet - WTP is not in RUN state\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (CHECK_PRISM_HEADER) {\n\t\t\t/*CWDebugLog(\"----------\\n\");\n\t\t\t   CWDebugLog(\"%d bytes read\\n\",n);\n\t\t\t   CWDebugLog(\"Prism header OK\\n\"); */\n\t\t\tif (n > PRISMH_LEN) {\n\t\t\t\tbyte0 = *(buffer + PRISMH_LEN);\n\n\t\t\t\tversion = byte0 & VERSION_MASK;\n\t\t\t\ttype = byte0 & TYPE_MASK;\n\t\t\t\tsubtype = byte0 & SUBTYPE_MASK;\n\t\t\t\tsubtype >>= 4;\n\n\t\t\t\t/*              if(version == (unsigned char) VERSION) {CWDebugLog(\"Version OK\\n\");}\n\t\t\t\t   else {CWDebugLog(\"Wrong Version\");} */\n\t\t\t\tif (type == (unsigned char)MANAGEMENT_TYPE) {\t//Management Frame\n\t\t\t\t\t//CWDebugLog(\"Management Frame\\n\");\n\t\t\t\t\t//CWDebugLog(\"Subtype: %d \", subtype);\n\t\t\t\t\tswitch (subtype) {\n\t\t\t\t\tcase ASSOCIATION_REQUEST_SUBTYPE:{\n\t\t\t\t\t\t\tif (!extractFrame(&frame, buffer, n)) {\n\t\t\t\t\t\t\t\tCWDebugLog(\"THR FRAME: Error extracting a frame\");\n\t\t\t\t\t\t\t\tEXIT_FRAME_THREAD(gRawSock);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\textractAddr(destAddr, sourceAddr, frame->msg);\n\n\t\t\t\t\t\t\tint k;\n\n\t\t\t\t\t\t\tfor (k = 0; k < MAC_ADDR_LEN; k++) {\n\t\t\t\t\t\t\t\tprintf(\"%02x\", sourceAddr[k]);\n\t\t\t\t\t\t\t\tif (k != MAC_ADDR_LEN - 1) {\n\t\t\t\t\t\t\t\t\tprintf(\":\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tprintf(\"\\n\");\n\t\t\t\t\t\t\tfflush(stdout);\n\n\t\t\t\t\t\t\tCW_CREATE_OBJECT_ERR(bindingValuesPtr,\n\t\t\t\t\t\t\t\t\t     CWBindingTransportHeaderValues,\n\t\t\t\t\t\t\t\t\t     EXIT_FRAME_THREAD(gRawSock);\n\t\t\t\t\t\t\t    );\n\t\t\t\t\t\t\textractFrameInfo((char *)buffer, &(bindingValuesPtr->RSSI),\n\t\t\t\t\t\t\t\t\t &(bindingValuesPtr->SNR),\n\t\t\t\t\t\t\t\t\t &(bindingValuesPtr->dataRate));\n\t\t\t\t\t\t\tCW_CREATE_OBJECT_ERR(listElement, CWBindingDataListElement,\n\t\t\t\t\t\t\t\t\t     EXIT_FRAME_THREAD(gRawSock);\n\t\t\t\t\t\t\t    );\n\t\t\t\t\t\t\tlistElement->frame = frame;\n\t\t\t\t\t\t\tlistElement->bindingValues = bindingValuesPtr;\n\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\tCWLockSafeList(gFrameList);\n\t\t\t\t\t\t\tCWAddElementToSafeListTail(gFrameList, listElement,\n\t\t\t\t\t\t\t\t\t\t   sizeof(CWBindingDataListElement));\n\t\t\t\t\t\t\tCWUnlockSafeList(gFrameList);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/*                      case ASSOCIATION_RESPONSE_SUBTYPE: {CWDebugLog(\"Association Response\\n\"); break;}\n\t\t\t\t\t\t   case REASSOCIATION_REQUEST_SUBTYPE: {CWDebugLog(\"Reassociation Request\\n\"); break;}\n\t\t\t\t\t\t   case REASSOCIATION_RESPONSE_SUBTYPE: {CWDebugLog(\"Reassociation Response\\n\"); break;}\n\t\t\t\t\t\t   case PROBE_REQUEST_SUBTYPE: {CWDebugLog(\"Probe Request\\n\"); break;}\n\t\t\t\t\t\t   case PROBE_RESPONSE_SUBTYPE: {CWDebugLog(\"Probe Response\\n\"); break;}\n\t\t\t\t\t\t   case RESERVED6_SUBTYPE: {CWDebugLog(\"Reserved\\n\"); break;}\n\t\t\t\t\t\t   case RESERVED7_SUBTYPE: {CWDebugLog(\"Reserved\\n\"); break;}\n\t\t\t\t\t\t   case BEACON_SUBTYPE: {CWDebugLog(\"Beacon\\n\"); break;}\n\t\t\t\t\t\t   case ATIM_SUBTYPE: {CWDebugLog(\"ATIM\\n\"); break;}\n\t\t\t\t\t\t   case DISASSOCIATION_SUBTYPE: {CWDebugLog(\"Disassociation\\n\"); break;}\n\t\t\t\t\t\t   case AUTHENTICATION_SUBTYPE: {CWDebugLog(\"Authentication\\n\"); break;}\n\t\t\t\t\t\t   case DEAUTHENTICATION_SUBTYPE: {CWDebugLog(\"Deauthentication\\n\"); break;} */\n\t\t\t\t\tdefault:{\n\t\t\t\t\t\t\t/*CWDebugLog(\"Unrecognized Frame\\n\"); */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (type == (unsigned char)CONTROL_TYPE) {\t//Control Frame\n\t\t\t\t\t/*                  CWDebugLog(\"Control Frame\\n\");\n\t\t\t\t\t   //CWDebugLog(\"Subtype: %d \", subtype);\n\t\t\t\t\t   switch (subtype)\n\t\t\t\t\t   {\n\t\t\t\t\t   case RESERVED0_SUBTYPE: {CWDebugLog(\"Reserved\\n\"); break;}\n\t\t\t\t\t   case RESERVED9_SUBTYPE: {CWDebugLog(\"Reserved\\n\"); break;}\n\t\t\t\t\t   case POWER_SAVE_SUBTYPE: {CWDebugLog(\"Power Save\\n\"); break;}\n\t\t\t\t\t   case RTS_SUBTYPE: {CWDebugLog(\"RTS\\n\"); break;}\n\t\t\t\t\t   case CTS_SUBTYPE: {CWDebugLog(\"CTS\\n\"); break;}\n\t\t\t\t\t   case ACKNOLEDGEMENT_SUBTYPE: {CWDebugLog(\"Acknoledgement\\n\"); break;}\n\t\t\t\t\t   case CF_END_SUBTYPE: {CWDebugLog(\"CF-End\\n\"); break;}\n\t\t\t\t\t   case CF_END_CF_ACK_SUBTYPE: {CWDebugLog(\"CF-End + CF-Ack\\n\"); break;}\n\t\t\t\t\t   default: {CWDebugLog(\"Unrecognized Frame\\n\");}\n\t\t\t\t\t   } */\n\t\t\t\t}\n\t\t\t\tif (type == (unsigned char)DATA_TYPE) {\n\t\t\t\t\t/*                  CWDebugLog(\"Data Frame\\n\");\n\t\t\t\t\t   //CWDebugLog(\"Subtype: %d \", subtype);\n\t\t\t\t\t   switch (subtype)\n\t\t\t\t\t   {\n\t\t\t\t\t   case DATA_SUBTYPE: {CWDebugLog(\"Data\\n\"); break;}\n\t\t\t\t\t   case DATA_CF_ACK_SUBTYPE: {CWDebugLog(\"Data + CF-Ack\\n\"); break;}\n\t\t\t\t\t   case DATA_CF_POLL_SUBTYPE: {CWDebugLog(\"Data + CF-Poll\\n\"); break;}\n\t\t\t\t\t   case DATA_CF_ACK_CF_POLL_SUBTYPE: {CWDebugLog(\"Data + CF-Ack + CF-Poll\\n\"); break;}\n\t\t\t\t\t   case NO_DATA_SUBTYPE: {CWDebugLog(\"Null Function (no data)\\n\"); break;}\n\t\t\t\t\t   case CF_ACK_SUBTYPE: {CWDebugLog(\"CF-Ack (no data)\\n\"); break;}\n\t\t\t\t\t   case CF_POLL_SUBTYPE: {CWDebugLog(\"CF-Poll (no data)\\n\"); break;}\n\t\t\t\t\t   case CF_ACK_CF_POLL_SUBTYPE: {CWDebugLog(\"CF-Ack + CF-Poll (no data)\\n\"); break;}\n\t\t\t\t\t   case RESERVED8_SUBTYPE: {CWDebugLog(\"Reserved\\n\"); break;}\n\t\t\t\t\t   case RESERVED15_SUBTYPE: {CWDebugLog(\"Reserved\\n\"); break;}\n\t\t\t\t\t   default: {CWDebugLog(\"Unrecognized Frame\\n\");}\n\t\t\t\t\t   } */\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\tCWDebugLog(\"Malformed Frame\");\n\t\t} else {\n\t\t\t//Assume it is 802.3\n\t\t\tif (n <= (gCWForceMTU - 20)) {\n\t\t\t\tif (!extract802_3_Frame(&frame, buffer, n)) {\n\t\t\t\t\tCWDebugLog(\"THR FRAME: Error extracting a frame\");\n\t\t\t\t\tEXIT_FRAME_THREAD(gRawSock);\n\t\t\t\t}\n\t\t\t\tCWDebugLog(\"Send 802.3 data(len:%d) to AC\", n);\n\t\t\t\t;\n\t\t\t\tCW_CREATE_OBJECT_ERR(listElement, CWBindingDataListElement, EXIT_FRAME_THREAD(gRawSock);\n\t\t\t\t    );\n\t\t\t\tlistElement->frame = frame;\n\t\t\t\tlistElement->bindingValues = NULL;\n\n\t\t\t\t//\n\t\t\t\tCWLockSafeList(gFrameList);\n\t\t\t\tCWAddElementToSafeListTail(gFrameList, listElement, sizeof(CWBindingDataListElement));\n\t\t\t\tCWUnlockSafeList(gFrameList);\n\t\t\t} else {\n\t\t\t\tCWDebugLog(\"size:%d of 802.3 data > MTU:%d\", n, gCWForceMTU - 20);\n\t\t\t}\n\t\t}\n\t}\n\n\tclose(gRawSock);\n\treturn (NULL);\n}\n"
  },
  {
    "path": "WTPFrameReceive.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_WTPFrameReceive_HEADER__\n#define __CAPWAP_WTPFrameReceive_HEADER__\n\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <linux/if_ether.h>\n#include <net/if.h>\n#include <sys/ioctl.h>\n#include <netpacket/packet.h>\n\n#include \"CWWTP.h\"\n\n#ifndef B_ENDIAN\n#define CHECK_PRISM_HEADER  (buffer[0]==MESSAGE_CODE_1) && \\\n                (buffer[1]==MESSAGE_CODE_2) && \\\n                (buffer[2]==MESSAGE_CODE_3) && \\\n                (buffer[3]==MESSAGE_CODE_4)\n#else\n#define CHECK_PRISM_HEADER  (buffer[3]==MESSAGE_CODE_1) && \\\n                (buffer[2]==MESSAGE_CODE_2) && \\\n                (buffer[1]==MESSAGE_CODE_3) && \\\n                (buffer[0]==MESSAGE_CODE_4)\n#endif\n\n//#define PROMODE_ON\n//#define FILTER_ON\n#define PRISMH_LEN      144\n#define RSSI_BYTE       68\n#define SIGNAL_BYTE     92\n#define NOISE_BYTE      104\n#define DATARATE_BYTE       116\n#define DEST_ADDR_START     4\n#define SOURCE_ADDR_START   10\n#define MESSAGE_CODE_1      68\n#define MESSAGE_CODE_2      0\n#define MESSAGE_CODE_3      0\n#define MESSAGE_CODE_4      0\n#define MAC_ADDR_LEN        6\n#define ATHEROS_CONV_VALUE  95\n\n#define ASSOCIATION_REQUEST_SUBTYPE 0\n#define ASSOCIATION_RESPONSE_SUBTYPE    1\n#define REASSOCIATION_REQUEST_SUBTYPE   2\n#define REASSOCIATION_RESPONSE_SUBTYPE  3\n#define PROBE_REQUEST_SUBTYPE       4\n#define PROBE_RESPONSE_SUBTYPE      5\n#define RESERVED6_SUBTYPE       6\n#define RESERVED7_SUBTYPE       7\n#define BEACON_SUBTYPE          8\n#define ATIM_SUBTYPE            9\n#define DISASSOCIATION_SUBTYPE      10\n#define AUTHENTICATION_SUBTYPE      11\n#define DEAUTHENTICATION_SUBTYPE    12\n\n#define RESERVED0_SUBTYPE       0\n#define RESERVED9_SUBTYPE       9\n#define POWER_SAVE_SUBTYPE      10\n#define RTS_SUBTYPE         11\n#define CTS_SUBTYPE         12\n#define ACKNOLEDGEMENT_SUBTYPE      13\n#define CF_END_SUBTYPE          14\n#define CF_END_CF_ACK_SUBTYPE       15\n\n#define DATA_SUBTYPE            0\n#define DATA_CF_ACK_SUBTYPE     1\n#define DATA_CF_POLL_SUBTYPE        2\n#define DATA_CF_ACK_CF_POLL_SUBTYPE 3\n#define NO_DATA_SUBTYPE         4\n#define CF_ACK_SUBTYPE          5\n#define CF_POLL_SUBTYPE         6\n#define CF_ACK_CF_POLL_SUBTYPE      7\n#define RESERVED8_SUBTYPE       8\n#define RESERVED15_SUBTYPE      15\n\n#endif\n"
  },
  {
    "path": "WTPFreqStatsReceive.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author : Antonio Davoli (antonio.davoli@gmail.com)                                      *\n *                                                                                         *\n *******************************************************************************************/\n\n#include \"WTPFreqStatsReceive.h\"\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveFreqStats(void *arg)\n{\n\tint recSock, rlen, k, fragmentsNum = 0;\n\n\tstruct sockaddr_in servaddr, client_addr;\n\tsocklen_t slen = sizeof(client_addr);\n\n\tchar buffer[PACKET_SIZE];\n\n\tCWProtocolMessage *completeMsgPtr = NULL;\n\tCWProtocolMessage *data = NULL;\n\tCWBindingTransportHeaderValues *bindingValuesPtr = NULL;\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n\t/* Create an Inet UDP socket for this thread (Receive freq/ack packets) */\n\n\tif ((recSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {\n\t\tCWDebugLog(\"Thread Frequency Receive Stats: Error creating socket\");\n\t\tCWExitThread();\n\t}\n\n\t/*  Set up address structure for server socket */\n\n\tservaddr.sin_family = AF_INET;\n\tservaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n\tservaddr.sin_port = htons(SERVER_PORT);\n\n\t/* Binding Socket */\n\n\tif (bind(recSock, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)) < 0) {\n\t\tCWDebugLog(\"Thread Frequency Receive Stats: Binding Socket Error\");\n\t\tclose(recSock);\n\t\tCWExitThread();\n\t}\n\n\tCW_REPEAT_FOREVER\t/* Receive data Loop */\n\t{\n\t\tmemset(buffer, 0, PACKET_SIZE);\n\t\tfragmentsNum = 0;\n\t\tk = 0;\n\t\trlen = 0;\n\n\t\tif ((rlen = recvfrom(recSock, buffer, PACKET_SIZE, 0, (struct sockaddr *)&client_addr, &slen)) > 0) {\n\t\t\t/* Creation of stats/ack message for AC */\n\n\t\t\tCW_CREATE_OBJECT_ERR(data, CWProtocolMessage, return 0;\n\t\t\t    );\n\t\t\tCW_CREATE_PROTOCOL_MESSAGE(*data, rlen, return 0;\n\t\t\t    );\n\n\t\t\tmemcpy(data->msg, buffer, rlen);\n\t\t\tdata->offset = rlen;\n\n\t\t\t/**************************************************************\n\t\t\t * 2009 Update:                                               *\n\t\t\t *                                                            *\n\t\t\t * Frequency Stats Message, like the QoS Data message are     *\n\t\t\t * encapsuled on Capwap Data Message.                         *\n\t\t\t * For distinguish the two types of message we use the fields *\n\t\t\t * of binding dataRate and SNR.                               *\n\t\t\t * Frequency Stats Message: dataRate=-1 && SNR=1              *\n\t\t\t * QoS Stats Message      : dataRate=-1                       *\n\t\t\t * ---------------------------------------------------------- *\n\t\t\t * For others Info: see  CWBinding.c                          *\n\t\t\t **************************************************************/\n\n\t\t\t/* In this function is tied the name of the socket: recSock */\n\t\t\tCW_CREATE_OBJECT_ERR(bindingValuesPtr, CWBindingTransportHeaderValues, EXIT_THREAD);\n\t\t\tbindingValuesPtr->dataRate = -1;\n\t\t\tbindingValuesPtr->SNR = 1;\n\n\t\t\t/* Capwap Message Assembling */\n\n\t\t\tif (CWAssembleDataMessage(&completeMsgPtr, &fragmentsNum, gWTPPathMTU, data, bindingValuesPtr,\n\t\t\t\t\t\t  CW_PACKET_PLAIN, 0) == CW_TRUE)\n\t\t\t{\n\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\n#ifdef CW_NO_DTLS\n\t\t\t\t\tif (!CWNetworkSendUnsafeConnected\n\t\t\t\t\t    (gWTPSocket, completeMsgPtr[k].msg, completeMsgPtr[k].offset)) {\n#else\n\t\t\t\t\tif (!CWSecuritySend\n\t\t\t\t\t    (gWTPSession, completeMsgPtr[k].msg, completeMsgPtr[k].offset)) {\n#endif\n\t\t\t\t\t\tCWDebugLog(\"Failure sending Request\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Free used Structures */\n\n\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t}\n\n\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(*data);\n\t\t\tCW_FREE_OBJECT(data);\n\t\t\tCW_FREE_OBJECT(bindingValuesPtr);\n\t\t} else {\n\t\t\tCWDebugLog(\"Thread Frequency Receive Stats: Error on recvfrom\");\n\t\t\tclose(recSock);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "WTPFreqStatsReceive.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author : Antonio Davoli (antonio.davoli@gmail.com)                                      *\n *                                                                                         *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_WTPFreqStatsReceive_HEADER__\n#define __CAPWAP_WTPFreqStatsReceive_HEADER__\n\n#include \"CWWTP.h\"\n#include <ctype.h>\n#include <netinet/in.h>\n#include <sys/un.h>\n\n#define SERVER_PORT 1237\n#define PACKET_SIZE 65536\n\n#define EXIT_THREAD CWLog(\"ERROR Handling Frequency Stats: application will be closed!\");       \\\n                close(recSock);                             \\\n                exit(1);\n\n/* Structs for frequencies' informations */\n\ntypedef unsigned char uint8;\n\n#define MAX_FREQ_LENGTH 16\n#define MAX_ESSID_LENGTH 32\n#define MAX_MAC_ADDR_LENGTH 18\t/* XX:XX:XX:XX:XX:XX */\n\ntypedef struct _quality {\n\tuint8 numerator;\n\tuint8 denominator;\n} quality;\n\ntypedef struct _FreqQualityInfo {\n\tuint8 version;\n\tchar ESSID[MAX_ESSID_LENGTH];\n\tchar Address[MAX_MAC_ADDR_LENGTH];\n\tuint8 channel;\n\tuint8 assocStations;\n\tuint8 throughStations;\n\tquality qualityLevel;\n\tint signalLevel;\n\tint noiseLevel;\n} FreqQualityInfo;\n\ntypedef struct _FREQ_MONITOR_DATA {\n\tint numberOfCells;\n\tFreqQualityInfo *qualityOfCells;\n} FREQ_MONITOR_DATA;\n\n#endif\n"
  },
  {
    "path": "WTPJoinState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nstatic CWBool gSuccessfulHandshake = CW_TRUE;\nint gCWWaitJoin = CW_JOIN_INTERVAL_DEFAULT;\nint gCWDiscoveryCount;\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\nvoid CWWTPWaitJoinExpired(CWTimerArg arg);\nCWBool CWAssembleJoinRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t     int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList);\n\nCWBool CWParseJoinResponseMessage(unsigned char *msg, int len, int seqNum, CWProtocolJoinResponseValues * valuesPtr);\n\nCWBool CWSaveJoinResponseMessage(CWProtocolJoinResponseValues * joinResponse);\n\n/*_____________________________________________________*/\n/*  *******************___FUNCTIONS___*******************  */\n\n/*\n * Manage Join State.\n */\nCWStateTransition CWWTPEnterJoin()\n{\n\n\tCWTimerID waitJoinTimer;\n\tint seqNum;\n\tCWProtocolJoinResponseValues values;\n\tCWStateTransition state = CW_ENTER_DISCOVERY;\n\tCWDebugLog(\"Checking if hostapd is connected...\");\n\tif (gRADIO_MAC[0] == 0xAA){\n\tCWDebugLog(\"Waiting for hostapd to connect...\");\n       \twhile(gRADIO_MAC[0] == 0xAA) sleep(1);\n\t}\n\telse {\n\tCWDebugLog(\"Hostapd is connected...\");\n\t}\n\n\tCWDebugLog(\"\\n\");\n\tCWDebugLog(\"######### Join State #########\");\n\n\t/* reset Join state */\n\tCWNetworkCloseSocket(gWTPSocket);\n#ifndef CW_NO_DTLS\n\tCWSecurityDestroySession(gWTPSession);\n\tCWSecurityDestroyContext(gWTPSecurityContext);\n#endif\n\tgWTPSecurityContext = NULL;\n\tgWTPSession = NULL;\n\n\t/* Initialize gACInfoPtr */\n\tgACInfoPtr = malloc(sizeof(CWACInfoValues));\n\tgACInfoPtr->ACIPv4ListInfo.ACIPv4ListCount = 0;\n\tgACInfoPtr->ACIPv4ListInfo.ACIPv4List = NULL;\n\tgACInfoPtr->ACIPv6ListInfo.ACIPv6ListCount = 0;\n\tgACInfoPtr->ACIPv6ListInfo.ACIPv6List = NULL;\n        CWDebugLog(\"State is %d\", state);\n\n        if (gWTPForceACAddress != NULL) {\n                CW_CREATE_OBJECT_ERR(gACInfoPtr, CWACInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n                    );\n                CWNetworkGetAddressForHost(gWTPForceACAddress, &(gACInfoPtr->preferredAddress));\n                gACInfoPtr->security = gWTPForceSecurity;\n\t\tstate = CW_ENTER_JOIN;\n\t\tCWDebugLog(\"State is %d\", state);\n        }\n\n\tif ((waitJoinTimer = timer_add(gCWWaitJoin, 0, CWWTPWaitJoinExpired, NULL)) == -1) {\n\t\treturn state;\n\t}\n\n\n\t/* Init DTLS session */\n\tif (!CWErr(CWNetworkInitSocketClient(&gWTPSocket, &(gACInfoPtr->preferredAddress)))) {\n\n\t\ttimer_rem(waitJoinTimer, NULL);\n\t\treturn state;\n\t}\n\tif (!CWErr(CWNetworkInitSocketClientDataChannel(&gWTPDataSocket, &(gACInfoPtr->preferredAddress)))) {\n\t\treturn state;\n\t}\n\tCWLog(\"Initiate Data Channel\");\n\tCWDebugLog(\"gWTPSocket:%d, gWTPDataSocket:%d\", gWTPSocket, gWTPDataSocket);\n\n#ifndef CW_NO_DTLS\n\tif (gACInfoPtr->security == CW_X509_CERTIFICATE) {\n\t\tif (!CWErr(CWSecurityInitContext(&gWTPSecurityContext,\n\t\t\t\t\t\t \"root.pem\", \"client.pem\", \"prova\", CW_TRUE, NULL))) {\n\n\t\t\ttimer_rem(waitJoinTimer, NULL);\n\t\t\tCWNetworkCloseSocket(gWTPSocket);\n\t\t\tgWTPSecurityContext = NULL;\n\t\t\treturn state;\n\t\t}\n\t} else {\n\t\t/* pre-shared keys */\n\t\tif (!CWErr(CWSecurityInitContext(&gWTPSecurityContext, NULL, NULL, NULL, CW_TRUE, NULL))) {\n\n\t\t\ttimer_rem(waitJoinTimer, NULL);\n\t\t\tCWNetworkCloseSocket(gWTPSocket);\n\t\t\tgWTPSecurityContext = NULL;\n       \t\t        return state;\n\n\t\t}\n\t}\n#endif\n\tCWThread thread_receiveFrame;\n\tif (!CWErr(CWCreateThread(&thread_receiveFrame, CWWTPReceiveDtlsPacket, (void *)gWTPSocket))) {\n\n\t\tCWLog(\"Error starting Thread that receive DTLS packet\");\n\t\ttimer_rem(waitJoinTimer, NULL);\n\t\tCWNetworkCloseSocket(gWTPSocket);\n#ifndef CW_NO_DTLS\n\t\tCWSecurityDestroyContext(gWTPSecurityContext);\n\t\tgWTPSecurityContext = NULL;\n\t\tgWTPSession = NULL;\n#endif\n\t\tif (gWTPForceACAddress != NULL) return CW_ENTER_JOIN;\n\t\telse return state;\n\t}\n\n\tCWThread thread_receiveDataFrame;\n\tif (!CWErr(CWCreateThread(&thread_receiveDataFrame, CWWTPReceiveDataPacket, (void *)gWTPDataSocket))) {\n\n\t\tCWLog(\"Error starting Thread that receive data packet\");\n\t\treturn state;\n\t}\n#ifndef CW_NO_DTLS\n\n\tif (!CWErr(CWSecurityInitSessionClient(gWTPSocket,\n\t\t\t\t\t       &(gACInfoPtr->preferredAddress),\n\t\t\t\t\t       gPacketReceiveList, gWTPSecurityContext, &gWTPSession, &gWTPPathMTU))) {\n\n\t\t/* error setting up DTLS session */\n\t\ttimer_rem(waitJoinTimer, NULL);\n\t\tCWNetworkCloseSocket(gWTPSocket);\n\t\tCWSecurityDestroyContext(gWTPSecurityContext);\n\t\tgWTPSecurityContext = NULL;\n\t\tgWTPSession = NULL;\n\t\treturn state;\n\t}\n#endif\n\tif (gCWForceMTU > 0) {\n\t\tgWTPPathMTU = gCWForceMTU;\n\t}\n\n\tCWDebugLog(\"Path MTU for this Session: %d\", gWTPPathMTU);\n\tCWDebugLog(\"Waiting for previous threads to be closed on AC\");\n\t//sleep(CW_NEIGHBORDEAD_INTERVAL_DEFAULT*2);\n\n\t/* send Join Request */\n\tseqNum = CWGetSeqNum();\n\n\tif (!CWErr(CWWTPSendAcknowledgedPacket(seqNum,\n\t\t\t\t\t       NULL,\n\t\t\t\t\t       CWAssembleJoinRequest,\n\t\t\t\t\t       (void *)CWParseJoinResponseMessage,\n\t\t\t\t\t       (void *)CWSaveJoinResponseMessage, &values))) {\n cw_join_err:\n\t\ttimer_rem(waitJoinTimer, NULL);\n\t\tCWNetworkCloseSocket(gWTPSocket);\n#ifndef CW_NO_DTLS\n\t\tCWSecurityDestroySession(gWTPSession);\n\t\tCWSecurityDestroyContext(gWTPSecurityContext);\n\t\tgWTPSecurityContext = NULL;\n\t\tgWTPSession = NULL;\n#endif\n                gWTPSecurityContext = NULL;\n                gWTPSession = NULL;\n\t\treturn state;\n\t}\n\n\ttimer_rem(waitJoinTimer, NULL);\n\n\tif (!gSuccessfulHandshake) {\n\t\t/* timer expired */\n\t\tgoto cw_join_err;\n\t}\n\n\tCWLog(\"Join Completed\");\n\n\treturn CW_ENTER_CONFIGURE;\n}\n\nvoid CWWTPWaitJoinExpired(CWTimerArg arg)\n{\n\n\tCWLog(\"WTP Wait Join Expired\");\n\tgSuccessfulHandshake = CW_FALSE;\n\tCWNetworkCloseSocket(gWTPSocket);\n}\n\nCWBool CWAssembleJoinRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t     int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 9;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWLog(\"Assembling Join Request Message Elements...\");\n\n\t/* Assemble Message Elements */\n\tif ((!(CWAssembleMsgElemLocationData(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPBoardData(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPDescriptor(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPIPv4Address(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPName(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemSessionID(&(msgElems[++k]), &gWTPSessionID[0]))) ||\n\t    (!(CWAssembleMsgElemWTPFrameTunnelMode(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPMACType(&(msgElems[++k])))) ||\n\t    (!(CWAssembleMsgElemWTPRadioInformation(&(msgElems[++k]))))\n\t    ) {\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\t/* error will be handled by the caller */\n\t\treturn CW_FALSE;\n\t}\n\n\tCWLog(\"Assembling and Sending Join Request Message ...\");\n\n\treturn CWAssembleMessage(messagesPtr,\n\t\t\t\t fragmentsNumPtr,\n\t\t\t\t PMTU,\n\t\t\t\t seqNum,\n\t\t\t\t CW_MSG_TYPE_VALUE_JOIN_REQUEST,\n\t\t\t\t msgElems, msgElemCount, msgElemsBinding, msgElemBindingCount);\n}\n\n/*\n * Parse Join Response and return informations in *valuesPtr.\n */\nCWBool CWParseJoinResponseMessage(unsigned char *msg, int len, int seqNum, CWProtocolJoinResponseValues * valuesPtr)\n{\n\n\tCWControlHeaderValues controlVal;\n\tCWProtocolMessage completeMsg;\n\tint offsetTillMessages;\n\tchar tmp_ABGNTypes;\n\tif (msg == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWDebugLog(\"Parsing Join Response...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\t/* error will be handled by the caller */\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\treturn CW_FALSE;\n\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_JOIN_RESPONSE)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Join Response as Expected\");\n\n\tif (controlVal.seqNum != seqNum)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Different Sequence Number\");\n\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\toffsetTillMessages = completeMsg.offset;\n\n\t/* Mauro */\n\tvaluesPtr->ACInfoPtr.IPv4AddressesCount = 0;\n\tvaluesPtr->ACInfoPtr.IPv6AddressesCount = 0;\n\n\t/* parse message elements */\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\t\tunsigned short int type = 0;\n\t\tunsigned short int len = 0;\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\n\t\tCWDebugLog(\"Parsing Message Element: %u, len: %u\", type, len);\n\t\t/*\n\t\t   valuesPtr->ACInfoPtr.IPv4AddressesCount = 0;\n\t\t   valuesPtr->ACInfoPtr.IPv6AddressesCount = 0;\n\t\t */\n\t\tvaluesPtr->ACIPv4ListInfo.ACIPv4ListCount = 0;\n\t\tvaluesPtr->ACIPv4ListInfo.ACIPv4List = NULL;\n\t\tvaluesPtr->ACIPv6ListInfo.ACIPv6ListCount = 0;\n\t\tvaluesPtr->ACIPv6ListInfo.ACIPv6List = NULL;\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_AC_DESCRIPTOR_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseACDescriptor(&completeMsg, len, &(valuesPtr->ACInfoPtr))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!CWParseWTPRadioInformation_FromAC(&completeMsg, len, &tmp_ABGNTypes))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_AC_IPV4_LIST_CW_TYPE:\n\t\t\tif (!(CWParseACIPv4List(&completeMsg, len, &(valuesPtr->ACIPv4ListInfo))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_AC_IPV6_LIST_CW_TYPE:\n\t\t\tif (!(CWParseACIPv6List(&completeMsg, len, &(valuesPtr->ACIPv6ListInfo))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:\n\t\t\tif (!(CWParseResultCode(&completeMsg, len, &(valuesPtr->code))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_AC_NAME_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseACName(&completeMsg, len, &(valuesPtr->ACInfoPtr.name))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV4_ADDRESS_CW_TYPE:\n\t\t\t/*\n\t\t\t * just count how many interfacess we\n\t\t\t * have, so we can allocate the array\n\t\t\t */\n\t\t\tvaluesPtr->ACInfoPtr.IPv4AddressesCount++;\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV6_ADDRESS_CW_TYPE:\n\t\t\t/*\n\t\t\t * just count how many interfacess we\n\t\t\t * have, so we can allocate the array\n\t\t\t */\n\t\t\tvaluesPtr->ACInfoPtr.IPv6AddressesCount++;\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\t\t/*\n\t\t\t   case CW_MSG_ELEMENT_SESSION_ID_CW_TYPE:\n\t\t\t   if(!(CWParseSessionID(&completeMsg, len, valuesPtr))) return CW_FALSE;\n\t\t\t   break;\n\t\t\t */\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\n\t\t/* CWDebugLog(\"bytes: %d/%d\", (completeMsg.offset-offsetTillMessages), controlVal.msgElemsLen); */\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\t/* actually read each interface info */\n\tCW_CREATE_ARRAY_ERR(valuesPtr->ACInfoPtr.IPv4Addresses,\n\t\t\t    valuesPtr->ACInfoPtr.IPv4AddressesCount,\n\t\t\t    CWProtocolIPv4NetworkInterface, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (valuesPtr->ACInfoPtr.IPv6AddressesCount > 0) {\n\n\t\tCW_CREATE_ARRAY_ERR(valuesPtr->ACInfoPtr.IPv6Addresses,\n\t\t\t\t    valuesPtr->ACInfoPtr.IPv6AddressesCount,\n\t\t\t\t    CWProtocolIPv6NetworkInterface, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t}\n\n\tint i = 0;\n\tint j = 0;\n\n\tcompleteMsg.offset = offsetTillMessages;\n\twhile ((completeMsg.offset - offsetTillMessages) < controlVal.msgElemsLen) {\n\t\tunsigned short int type = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int len = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &len);\n\n\t\tswitch (type) {\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV4_ADDRESS_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseCWControlIPv4Addresses(&completeMsg,\n\t\t\t\t\t\t\t    len, &(valuesPtr->ACInfoPtr.IPv4Addresses[i]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\ti++;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_CW_CONTROL_IPV6_ADDRESS_CW_TYPE:\n\t\t\t/* will be handled by the caller */\n\t\t\tif (!(CWParseCWControlIPv6Addresses(&completeMsg,\n\t\t\t\t\t\t\t    len, &(valuesPtr->ACInfoPtr.IPv6Addresses[j]))))\n\t\t\t\treturn CW_FALSE;\n\t\t\tj++;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcompleteMsg.offset += len;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveJoinResponseMessage(CWProtocolJoinResponseValues * joinResponse)\n{\n\n\tif (joinResponse == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif ((joinResponse->code == CW_PROTOCOL_SUCCESS) || (joinResponse->code == CW_PROTOCOL_SUCCESS_NAT)) {\n\n\t\tif (gACInfoPtr == NULL)\n\t\t\treturn CWErrorRaise(CW_ERROR_NEED_RESOURCE, NULL);\n\n\t\tgACInfoPtr->name = (joinResponse->ACInfoPtr).name;\n\t\tgACInfoPtr->stations = (joinResponse->ACInfoPtr).stations;\n\t\tgACInfoPtr->limit = (joinResponse->ACInfoPtr).limit;\n\t\tgACInfoPtr->activeWTPs = (joinResponse->ACInfoPtr).activeWTPs;\n\t\tgACInfoPtr->maxWTPs = (joinResponse->ACInfoPtr).maxWTPs;\n\t\tgACInfoPtr->security = (joinResponse->ACInfoPtr).security;\n\t\tgACInfoPtr->RMACField = (joinResponse->ACInfoPtr).RMACField;\n\n\t\t/* BUG-ML07\n\t\t * Before overwriting the field vendorInfos we'd better\n\t\t * free it (it was allocated during the Discovery State by\n\t\t * the function CWParseACDescriptor()).\n\t\t *\n\t\t * 19/10/2009 - Donato Capitella\n\t\t */\n\t\t// Applies only if Discovey has run \n\t\tif (gCWDiscoveryCount != 0) {\n\t\t\tint i;\n\t\t\tfor (i = 0; i < gACInfoPtr->vendorInfos.vendorInfosCount; i++) {\n\t\t\t\tCW_FREE_OBJECT(gACInfoPtr->vendorInfos.vendorInfos[i].valuePtr);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(gACInfoPtr->vendorInfos.vendorInfos);\n\t\t\tgWTPForceACAddress = NULL;\n\t\t\tif (joinResponse->ACIPv4ListInfo.ACIPv4ListCount > 0) {\n\t\t\t\tgACInfoPtr->ACIPv4ListInfo.ACIPv4ListCount = joinResponse->ACIPv4ListInfo.ACIPv4ListCount;\n\t\t\t\tgACInfoPtr->ACIPv4ListInfo.ACIPv4List = joinResponse->ACIPv4ListInfo.ACIPv4List;\n\t\t\t}\n\t\t\tif (joinResponse->ACIPv6ListInfo.ACIPv6ListCount > 0) {\n\n\t\t\t\tgACInfoPtr->ACIPv6ListInfo.ACIPv6ListCount = joinResponse->ACIPv6ListInfo.ACIPv6ListCount;\n\t\t\t\tgACInfoPtr->ACIPv6ListInfo.ACIPv6List = joinResponse->ACIPv6ListInfo.ACIPv6List;\n\t\t\t}\n\t\t}\n\n\t\tgACInfoPtr->vendorInfos = (joinResponse->ACInfoPtr).vendorInfos;\n\n\t\t/*\n\t\t * This field name was allocated for storing the AC name; however, it\n\t\t * doesn't seem to be used and it is certainly lost when we exit\n\t\t * CWWTPEnterJoin() as joinResponse is actually a local variable of that\n\t\t * function.\n\t\t *\n\t\t * Thus, it seems good to free it now.\n\t\t *\n\t\t * BUG ML03\n\t\t * 16/10/2009 - Donato Capitella\n\t\t */\n\t\tCW_FREE_OBJECT(joinResponse->ACInfoPtr.name);\n\t\t/* BUG ML08 */\n\t\tCW_FREE_OBJECT(joinResponse->ACInfoPtr.IPv4Addresses);\n\n\t\tCWDebugLog(\"Join Response Saved\");\n\t\treturn CW_TRUE;\n\t} else {\n\t\tCWDebugLog(\"Join Response said \\\"Failure\\\"\");\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Join Response as Expected\");\n\t}\n}\n"
  },
  {
    "path": "WTPProtocol.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n#include \"WTPipcHostapd.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/*____________________________________________________________________________*/\n/*  *****************************___ASSEMBLE___*****************************  */\nCWBool CWAssembleMsgElemACName(CWProtocolMessage * msgPtr)\n{\n\tchar *name;\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tname = CWWTPGetACName();\n\tCWDebugLog(\"AC Name: %s\", name);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, strlen(name), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStoreStr(msgPtr, name);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_AC_NAME_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemACNameWithIndex(CWProtocolMessage * msgPtr)\n{\n\tconst int ac_Index_length = 1;\n\tCWACNamesWithIndex ACsinfo;\n\tCWProtocolMessage *msgs;\n\tint len = 0;\n\tint i;\n\tint j;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!CWWTPGetACNameWithIndex(&ACsinfo)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgs, ACsinfo.count, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t// create message\n\tfor (i = 0; i < ACsinfo.count; i++) {\n\t\t// create message\n\t\tCW_CREATE_PROTOCOL_MESSAGE(msgs[i], ac_Index_length + strlen(ACsinfo.ACNameIndex[i].ACName),\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tCWProtocolStore8(&(msgs[i]), ACsinfo.ACNameIndex[i].index);\t// ID of the AC\n\t\tCWProtocolStoreStr(&(msgs[i]), ACsinfo.ACNameIndex[i].ACName);\t// name of the AC\n\t\tif (!(CWAssembleMsgElem(&(msgs[i]), CW_MSG_ELEMENT_AC_NAME_INDEX_CW_TYPE))) {\n\t\t\tfor (j = i; j >= 0; j--) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[j]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(ACsinfo.ACNameIndex);\n\t\t\tCW_FREE_OBJECT(msgs);\n\t\t\treturn CW_FALSE;\n\t\t}\n//      CWDebugLog(\"AC Name with index: %d - %s\", ACsinfo.ACNameIndex[i].index, ACsinfo.ACNameIndex[i].ACName);\n\t\tlen += msgs[i].offset;\n\t}\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < ACsinfo.count; i++) {\n\t\tCWProtocolStoreMessage(msgPtr, &(msgs[i]));\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[i]);\n\t}\n\n\tCW_FREE_OBJECT(msgs);\n\n\t/*\n\t * They free ACNameIndex, which is an array of CWACNameWithIndexValues,\n\t * but nobody cares to free the actual strings that were allocated as fields\n\t * of the CWACNameWithIndexValues structures in the CWWTPGetACNameWithIndex()\n\t * function.. Here we take care of this.\n\t *\n\t * BUG ML06\n\t * 16/10/2009 - Donato Capitella\n\t */\n\tCW_FREE_OBJECT(ACsinfo.ACNameIndex[0].ACName);\n\tCW_FREE_OBJECT(ACsinfo.ACNameIndex[1].ACName);\n\n\tCW_FREE_OBJECT(ACsinfo.ACNameIndex);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemDataTransferData(CWProtocolMessage * msgPtr, int data_type)\n{\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tchar *debug_data = \" #### DATA DEBUG INFO #### \";\t//to be changed...\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 2 + strlen(debug_data), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, data_type);\n\tCWProtocolStore8(msgPtr, strlen(debug_data));\n\tCWProtocolStoreStr(msgPtr, debug_data);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_DATA_TRANSFER_DATA_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemDiscoveryType(CWProtocolMessage * msgPtr)\n{\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 1, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n//  CWDebugLog(\"Discovery Type: %d\", CWWTPGetDiscoveryType());\n\n\tCWProtocolStore8(msgPtr, CWWTPGetDiscoveryType());\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_DISCOVERY_TYPE_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemLocationData(CWProtocolMessage * msgPtr)\n{\n\tCWDebugLog(\"CWAssembleMsgElemLocationData()\");\n\tchar *location;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tlocation = CWWTPGetLocation();\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, strlen(location), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWDebugLog(\"Location Data: %s\", location);\n\tCWProtocolStoreStr(msgPtr, location);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_LOCATION_DATA_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemStatisticsTimer(CWProtocolMessage * msgPtr)\n{\n\tconst int statistics_timer_length = 2;\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, statistics_timer_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore16(msgPtr, CWWTPGetStatisticsTimer());\n\n//  CWDebugLog(\"Statistics Timer: %d\", CWWTPGetStatisticsTimer());\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_STATISTICS_TIMER_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPBoardData(CWProtocolMessage * msgPtr)\n{\n\tCWDebugLog(\"CWAssembleMsgElemWTPBoardData()\");\n\tconst int VENDOR_ID_LENGTH = 4;\t//Vendor Identifier is 4 bytes long\n\tconst int TLV_HEADER_LENGTH = 4;\t//Type and Length of a TLV field is 4 byte long\n\tCWWTPVendorInfos infos;\n\tint i, size = 0;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// get infos\n\tif (!CWWTPGetBoardData(&infos)) {\n\t\treturn CW_FALSE;\n\t}\n\t//Calculate msg elem size\n\tsize = VENDOR_ID_LENGTH;\n\tfor (i = 0; i < infos.vendorInfosCount; i++) {\n\t\tsize += (TLV_HEADER_LENGTH + ((infos.vendorInfos)[i]).length);\n\t}\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, size, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore32(msgPtr, ((infos.vendorInfos)[0].vendorIdentifier));\n\tfor (i = 0; i < infos.vendorInfosCount; i++) {\n\t\tCWProtocolStore16(msgPtr, ((infos.vendorInfos)[i].type));\n\t\tCWProtocolStore16(msgPtr, ((infos.vendorInfos)[i].length));\n\n\t\tif ((infos.vendorInfos)[i].length == 4) {\n\t\t\t*((infos.vendorInfos)[i].valuePtr) = htonl(*((infos.vendorInfos)[i].valuePtr));\n\t\t}\n\n\t\tCWProtocolStoreRawBytes(msgPtr, (unsigned char *)((infos.vendorInfos)[i].valuePtr),\n\t\t\t\t\t(infos.vendorInfos)[i].length);\n\n//      CWDebugLog(\"Board Data: %d - %d - %d - %d\", (infos.vendorInfos)[i].vendorIdentifier, (infos.vendorInfos)[i].type, (infos.vendorInfos)[i].length, *((infos.vendorInfos)[i].valuePtr));\n\t}\n\n\tCWWTPDestroyVendorInfos(&infos);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_BOARD_DATA_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemVendorSpecificPayload(CWProtocolMessage * msgPtr)\n{\n\tconst int VENDOR_ID_LENGTH = 4;\t//Vendor Identifier is 4 bytes long\n\tconst int ELEMENT_ID = 2;\t//Type and Length of a TLV field is 4 byte long\n\tconst int DATA_LEN = 2;\n\tCWWTPVendorInfos infos;\n\tint size = 0;\n\tint element_id_zero = 0;\n\tint data_zero = 0;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// get infos\n\tif (!CWWTPGetBoardData(&infos)) {\n\t\treturn CW_FALSE;\n\t}\n\t//Calculate msg elem size\n\tsize = VENDOR_ID_LENGTH + ELEMENT_ID + DATA_LEN;\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, size, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore32(msgPtr, ((infos.vendorInfos)[0].vendorIdentifier));\n\tCWProtocolStore16(msgPtr, element_id_zero);\n\tCWProtocolStore16(msgPtr, data_zero);\n\n\tCWWTPDestroyVendorInfos(&infos);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_BW_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPDescriptor(CWProtocolMessage * msgPtr)\n{\n\tconst int GENERIC_RADIO_INFO_LENGTH = 5;\t//First 4 bytes for Max Radios, Radios In Use and Num Encryption Capability\n\tconst int VENDOR_ID_LENGTH = 4;\t//Vendor Identifier is 4 bytes long\n\tconst int TLV_HEADER_LENGTH = 4;\t//Type and Length of a TLV field is 4 byte long\n\tCWWTPEncryptCaps encc;\n\tCWWTPVendorInfos infos;\n\tint i, size = 0;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// get infos\n\tif (!CWWTPGetVendorInfos(&infos)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!CWWTPGetEncCapabilities(&encc)) {\t// encryption capabilities\n\t\treturn CW_FALSE;\n\t}\n\n\t//Calculate msg elem size\n\tsize = GENERIC_RADIO_INFO_LENGTH;\n\tfor (i = 0; i < encc.encryptCapsCount; i++) {\n\t\tsize += 3;\n\t}\n\tfor (i = 0; i < infos.vendorInfosCount; i++) {\n\t\tsize += (VENDOR_ID_LENGTH + TLV_HEADER_LENGTH + ((infos.vendorInfos)[i]).length);\n\t}\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, size, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, CWWTPGetMaxRadios());\t// number of radios supported by the WTP\n\tCWProtocolStore8(msgPtr, CWWTPGetRadiosInUse());\t// number of radios present in the WTP\n\n\tCWProtocolStore8(msgPtr, encc.encryptCapsCount);\n\tfor (i = 0; i < encc.encryptCapsCount; i++) {\n\t\tCWProtocolStore8(msgPtr, (encc.encryptCaps)[i].WBID & 0x1f);\n\t\tCWProtocolStore16(msgPtr, (encc.encryptCaps)[i].encryptionCapabilities);\n\t}\n\n\tfor (i = 0; i < infos.vendorInfosCount; i++) {\n\t\tCWProtocolStore32(msgPtr, ((infos.vendorInfos)[i].vendorIdentifier));\n\t\tCWProtocolStore16(msgPtr, ((infos.vendorInfos)[i].type));\n\t\tCWProtocolStore16(msgPtr, ((infos.vendorInfos)[i].length));\n\n\t\tif ((infos.vendorInfos)[i].length == 4) {\n\t\t\t*((infos.vendorInfos)[i].valuePtr) = htonl(*((infos.vendorInfos)[i].valuePtr));\n\t\t}\n\n\t\tCWProtocolStoreRawBytes(msgPtr, (unsigned char *)((infos.vendorInfos)[i].valuePtr),\n\t\t\t\t\t(infos.vendorInfos)[i].length);\n\n//      CWDebugLog(\"WTP Descriptor Vendor ID: %d\", (infos.vendorInfos)[i].vendorIdentifier);\n//      CWDebugLog(\"WTP Descriptor Type: %d\", (infos.vendorInfos)[i].type);\n//      CWDebugLog(\"WTP Descriptor Length: %d\", (infos.vendorInfos)[i].length);\n//      CWDebugLog(\"WTP Descriptor Value: %d\", *((infos.vendorInfos)[i].valuePtr));\n\n\t\t//CWDebugLog(\"Vendor Info \\\"%d\\\" = %d - %d - %d\", i, (infos.vendorInfos)[i].vendorIdentifier, (infos.vendorInfos)[i].type, (infos.vendorInfos)[i].length);\n\t}\n\n\tCWWTPDestroyVendorInfos(&infos);\n\tCWWTPDestroyEncCapabilities(&encc);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_DESCRIPTOR_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPFrameTunnelMode(CWProtocolMessage * msgPtr)\n{\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 1, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n//  CWDebugLog(\"Frame Tunnel Mode: %d\", CWWTPGetFrameTunnelMode());\n\tCWProtocolStore8(msgPtr, CWWTPGetFrameTunnelMode());\t// frame encryption\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_FRAME_TUNNEL_MODE_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPIPv4Address(CWProtocolMessage * msgPtr)\n{\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 4, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n//  CWDebugLog(\"WTP IPv4 Address: %d\", CWWTPGetIPv4Address());\n\tCWProtocolStore32(msgPtr, CWWTPGetIPv4Address());\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_IPV4_ADDRESS_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPMACType(CWProtocolMessage * msgPtr)\n{\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 1, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n//  CWDebugLog(\"WTP MAC Type: %d\", CWWTPGetMACType());\n\tCWProtocolStore8(msgPtr, CWWTPGetMACType());\t// mode of operation of the WTP (local, split, ...)\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_MAC_TYPE_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPRadioInformation(CWProtocolMessage * msgPtr)\n{\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 5, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tunsigned char wtp_r_info;\n\twtp_r_info = CWTP_get_WTP_Radio_Information();\n\tint radioID = 0;\n\n\tCWProtocolStore8(msgPtr, radioID);\n\tCWProtocolStore8(msgPtr, 0);\n\tCWProtocolStore8(msgPtr, 0);\n\tCWProtocolStore8(msgPtr, 0);\n\tCWProtocolStore8(msgPtr, wtp_r_info);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_IEEE80211_WTP_RADIO_INFORMATION_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemSupportedRates(CWProtocolMessage * msgPtr)\n{\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 9, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tunsigned char tmp_sup_rate[8];\n\tCWWTP_get_WTP_Rates(tmp_sup_rate);\n\n\tint radioID = 0;\n\n\tCWProtocolStore8(msgPtr, radioID);\n\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[0]);\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[1]);\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[2]);\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[3]);\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[4]);\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[5]);\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[6]);\n\tCWProtocolStore8(msgPtr, tmp_sup_rate[7]);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_IEEE80211_SUPPORTED_RATES_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemMultiDomainCapability(CWProtocolMessage * msgPtr)\n{\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, 8, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tunsigned char tmp_mdc[6];\n\tCWWTP_get_WTP_MDC(tmp_mdc);\n\n\tint radioID = 0;\n\n\tCWProtocolStore8(msgPtr, radioID);\n\tCWProtocolStore8(msgPtr, 0);\n\n\tCWProtocolStore8(msgPtr, tmp_mdc[0]);\n\tCWProtocolStore8(msgPtr, tmp_mdc[1]);\n\tCWProtocolStore8(msgPtr, tmp_mdc[2]);\n\tCWProtocolStore8(msgPtr, tmp_mdc[3]);\n\tCWProtocolStore8(msgPtr, tmp_mdc[4]);\n\tCWProtocolStore8(msgPtr, tmp_mdc[5]);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_IEEE80211_MULTI_DOMAIN_CAPABILITY_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPName(CWProtocolMessage * msgPtr)\n{\n\tchar *name;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tname = CWWTPGetName();\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, strlen(name), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n//  CWDebugLog(\"WTPName: %s\", name);\n\tCWProtocolStoreStr(msgPtr, name);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_NAME_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemWTPOperationalStatistics(CWProtocolMessage * msgPtr, int radio)\n{\n\tconst int operational_statistics_length = 4;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (radio < 0 || radio >= gRadiosInfo.radioCount)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, operational_statistics_length,\n\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, radio);\n\tCWProtocolStore8(msgPtr, gRadiosInfo.radiosInfo[radio].TxQueueLevel);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].wirelessLinkFramesPerSec);\n\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"WTPOperationalStatistics of radio \\\"%d\\\": %d - %d\", radio,gRadiosInfo.radiosInfo[radio].TxQueueLevel,  gRadiosInfo.radiosInfo[radio].wirelessLinkFramesPerSec);\n\n\tCWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_OPERAT_STATISTICS_CW_TYPE);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemWTPRadioStatistics(CWProtocolMessage * msgPtr, int radio)\n{\n\tconst int radio_statistics_length = 20;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (radio < 0 || radio > gRadiosInfo.radioCount)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, radio_statistics_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore8(msgPtr, radio);\n\tCWProtocolStore8(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.lastFailureType);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.resetCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.SWFailureCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.HWFailuireCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.otherFailureCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.unknownFailureCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.configUpdateCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.channelChangeCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.bandChangeCount);\n\tCWProtocolStore16(msgPtr, gRadiosInfo.radiosInfo[radio].statistics.currentNoiseFloor);\n\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"WTPRadioStatistics of radio: \\\"%d\\\"\", radio);\n//  CWDebugLog(\"WTPRadioStatistics(1): %d - %d - %d\", gRadiosInfo.radiosInfo[radio].statistics.lastFailureType, gRadiosInfo.radiosInfo[radio].statistics.resetCount, gRadiosInfo.radiosInfo[radio].statistics.SWFailureCount);\n//  CWDebugLog(\"WTPRadioStatistics(2): %d - %d - %d\", gRadiosInfo.radiosInfo[radio].statistics.HWFailuireCount, gRadiosInfo.radiosInfo[radio].statistics.otherFailureCount, gRadiosInfo.radiosInfo[radio].statistics.unknownFailureCount);\n//  CWDebugLog(\"WTPRadioStatistics(3): %d - %d - %d - %d\", gRadiosInfo.radiosInfo[radio].statistics.configUpdateCount, gRadiosInfo.radiosInfo[radio].statistics.channelChangeCount,gRadiosInfo.radiosInfo[radio].statistics.bandChangeCount,gRadiosInfo.radiosInfo[radio].statistics.currentNoiseFloor);\n\n\t//return CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_RADIO_STATISTICS_CW_TYPE);\n\n\tCWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_RADIO_STATISTICS_CW_TYPE);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemWTPRebootStatistics(CWProtocolMessage * msgPtr)\n{\n\tconst int reboot_statistics_length = 15;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, reboot_statistics_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCWProtocolStore16(msgPtr, gWTPRebootStatistics.rebootCount);\n\tCWProtocolStore16(msgPtr, gWTPRebootStatistics.ACInitiatedCount);\n\tCWProtocolStore16(msgPtr, gWTPRebootStatistics.linkFailurerCount);\n\tCWProtocolStore16(msgPtr, gWTPRebootStatistics.SWFailureCount);\n\tCWProtocolStore16(msgPtr, gWTPRebootStatistics.HWFailuireCount);\n\tCWProtocolStore16(msgPtr, gWTPRebootStatistics.otherFailureCount);\n\tCWProtocolStore16(msgPtr, gWTPRebootStatistics.unknownFailureCount);\n\tCWProtocolStore8(msgPtr, gWTPRebootStatistics.lastFailureType);\n\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"WTPRebootStat(1): %d - %d - %d\", gWTPRebootStatistics.rebootCount, gWTPRebootStatistics.ACInitiatedCount, gWTPRebootStatistics.linkFailurerCount);\n//  CWDebugLog(\"WTPRebootStat(2): %d - %d - %d\", gWTPRebootStatistics.SWFailureCount, gWTPRebootStatistics.HWFailuireCount, gWTPRebootStatistics.otherFailureCount);\n//  CWDebugLog(\"WTPRebootStat(3): %d - %d\", gWTPRebootStatistics.unknownFailureCount, gWTPRebootStatistics.lastFailureType);\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_WTP_REBOOT_STATISTICS_CW_TYPE);\n}\n\n//test version\nCWBool CWAssembleMsgElemDuplicateIPv4Address(CWProtocolMessage * msgPtr)\n{\n\tconst int duplicate_ipv4_length = 11;\n\tunsigned char *macAddress;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, duplicate_ipv4_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"Duplicate IPv4 Address: %d\", CWWTPGetIPv4Address());\n\n\tCWProtocolStore32(msgPtr, CWWTPGetIPv4Address());\n\n\tCWProtocolStore8(msgPtr, CWWTPGetIPv4StatusDuplicate());\n\n\tCWProtocolStore8(msgPtr, 6);\n\n\tCW_CREATE_ARRAY_ERR(macAddress, 6, unsigned char, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tmacAddress[0] = 103;\n\tmacAddress[1] = 204;\n\tmacAddress[2] = 204;\n\tmacAddress[3] = 190;\n\tmacAddress[4] = 180;\n\tmacAddress[5] = 0;\n\n\tCWProtocolStoreRawBytes(msgPtr, macAddress, 6);\n\tCW_FREE_OBJECT(macAddress);\n\n\t//CWProtocolStore8(msgPtr, CWWTPGetIPv4StatusDuplicate());\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_DUPLICATE_IPV4_ADDRESS_CW_TYPE);\n}\n\n//test version\nCWBool CWAssembleMsgElemDuplicateIPv6Address(CWProtocolMessage * msgPtr)\n{\n\tconst int duplicate_ipv6_length = 23;\n\tunsigned char *macAddress;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\t// create message\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, duplicate_ipv6_length, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n//  CWDebugLog(\"\");\n//  CWDebugLog(\"Duplicate IPv6 Address\");\n\n\tstruct sockaddr_in6 myAddr;\n\tCWWTPGetIPv6Address(&myAddr);\n\tCWProtocolStoreRawBytes(msgPtr, myAddr.sin6_addr.s6_addr, 16);\n\n\tCWProtocolStore8(msgPtr, CWWTPGetIPv6StatusDuplicate());\n\n\tCWProtocolStore8(msgPtr, 6);\n\n\tCW_CREATE_ARRAY_ERR(macAddress, 6, unsigned char, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tmacAddress[0] = 103;\n\tmacAddress[1] = 204;\n\tmacAddress[2] = 204;\n\tmacAddress[3] = 190;\n\tmacAddress[4] = 180;\n\tmacAddress[5] = 0;\n\n\tCWProtocolStoreRawBytes(msgPtr, macAddress, 6);\n\tCW_FREE_OBJECT(macAddress);\n\n\t//CWProtocolStore8(msgPtr, CWWTPGetIPv6StatusDuplicate());\n\n\treturn CWAssembleMsgElem(msgPtr, CW_MSG_ELEMENT_DUPLICATE_IPV6_ADDRESS_CW_TYPE);\n}\n\nCWBool CWAssembleMsgElemRadioAdminState(CWProtocolMessage * msgPtr)\n{\n\tconst int radio_Admin_State_Length = 2;\n\tCWRadiosAdminInfo infos;\n\tCWProtocolMessage *msgs;\n\tint len = 0;\n\tint i;\n\tint j;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!CWGetWTPRadiosAdminState(&infos)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgs, (infos.radiosCount), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\t// create message\n\t\tCW_CREATE_PROTOCOL_MESSAGE(msgs[i], radio_Admin_State_Length,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].ID);\t// ID of the radio\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].state);\t// state of the radio\n\t\t//CWProtocolStore8(&(msgs[i]), infos.radios[i].cause);\n\n\t\tif (!(CWAssembleMsgElem(&(msgs[i]), CW_MSG_ELEMENT_RADIO_ADMIN_STATE_CW_TYPE))) {\n\t\t\tfor (j = i; j >= 0; j--) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[j]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(infos.radios);\n\t\t\tCW_FREE_OBJECT(msgs);\n\t\t\treturn CW_FALSE;\n\t\t}\n\n\t\tlen += msgs[i].offset;\n//      CWDebugLog(\"Radio Admin State: %d - %d - %d\", infos.radios[i].ID, infos.radios[i].state, infos.radios[i].cause);\n\t}\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\tCWProtocolStoreMessage(msgPtr, &(msgs[i]));\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[i]);\n\t}\n\n\tCW_FREE_OBJECT(msgs);\n\tCW_FREE_OBJECT(infos.radios);\n\n\treturn CW_TRUE;\n}\n\n//if radioID is negative return Radio Operational State for all radios\nCWBool CWAssembleMsgElemRadioOperationalState(int radioID, CWProtocolMessage * msgPtr)\n{\n\tconst int radio_Operational_State_Length = 3;\n\tCWRadiosOperationalInfo infos;\n\tCWProtocolMessage *msgs;\n\tint len = 0;\n\tint i;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!(CWGetWTPRadiosOperationalState(radioID, &infos))) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgs, (infos.radiosCount), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\t// create message\n\t\tCW_CREATE_PROTOCOL_MESSAGE(msgs[i], radio_Operational_State_Length,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].ID);\t// ID of the radio\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].state);\t// state of the radio\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].cause);\n\n\t\tif (!(CWAssembleMsgElem(&(msgs[i]), CW_MSG_ELEMENT_RADIO_OPERAT_STATE_CW_TYPE))) {\n\t\t\tint j;\n\t\t\tfor (j = i; j >= 0; j--) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[j]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(infos.radios);\n\t\t\tCW_FREE_OBJECT(msgs);\n\t\t\treturn CW_FALSE;\n\t\t}\n\n\t\tlen += msgs[i].offset;\n//      CWDebugLog(\"Radio Operational State: %d - %d - %d\", infos.radios[i].ID, infos.radios[i].state, infos.radios[i].cause);\n\t}\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\tCWProtocolStoreMessage(msgPtr, &(msgs[i]));\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[i]);\n\t}\n\n\tCW_FREE_OBJECT(msgs);\n\tCW_FREE_OBJECT(infos.radios);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleMsgElemDecryptErrorReport(CWProtocolMessage * msgPtr, int radioID)\n{\n\tint decrypy_Error_Report_Length = 0;\n\tCWDecryptErrorReportInfo infos;\n\tCWProtocolMessage *msgs;\n\tint len = 0;\n\tint i;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (!(CWGetDecryptErrorReport(radioID, &infos))) {\n\t\treturn CW_FALSE;\n\t}\n\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgs, (infos.radiosCount), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\t// create message\n\t\tdecrypy_Error_Report_Length = 2 + sizeof(CWMACAddress) * (infos.radios[i].numEntries);\n\n\t\tCW_CREATE_PROTOCOL_MESSAGE(msgs[i], decrypy_Error_Report_Length,\n\t\t\t\t\t   return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].ID);\t// ID of the radio\n\t\tCWProtocolStore8(&(msgs[i]), infos.radios[i].numEntries);\t// state of the radio\n\n\t\tCWProtocolStore8(&(msgs[i]), (unsigned char)sizeof(CWMACAddress) * (infos.radios[i].numEntries));\n\n\t\tCWProtocolStoreRawBytes(&(msgs[i]), (unsigned char *)*(infos.radios[i].decryptErrorMACAddressList),\n\t\t\t\t\tsizeof(CWMACAddress) * (infos.radios[i].numEntries));\n\n\t\t/*\n\t\t   CWDebugLog(\"###numEntries = %d\", infos.radios[i].numEntries);\n\t\t   CWDebugLog(\"j = %d\", sizeof(CWMACAddress)*(infos.radios[i].numEntries));\n\n\t\t   int j;\n\t\t   for (j=(sizeof(CWMACAddress)*(infos.radios[i].numEntries)); j>0; j--)\n\t\t   CWDebugLog(\"##(%d/6) = %d\", j, msgs[i].msg[(msgs[i].offset)-j]);\n\t\t */\n\n\t\tif (!(CWAssembleMsgElem(&(msgs[i]), CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_CW_TYPE))) {\n\t\t\tint j;\n\t\t\tfor (j = i; j >= 0; j--) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[j]);\n\t\t\t}\n\t\t\tfor (j = 0; j < infos.radiosCount; j++) {\n\t\t\t\tCW_FREE_OBJECT(infos.radios[j].decryptErrorMACAddressList);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(infos.radios);\n\t\t\tCW_FREE_OBJECT(msgs);\n\t\t\treturn CW_FALSE;\n\t\t}\n\n\t\tlen += msgs[i].offset;\n//      CWDebugLog(\"Radio Decrypt Error Report of radio \\\"%d\\\" = %d\", infos.radios[i].ID, infos.radios[i].numEntries);\n\t}\n\n\tCW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\tCWProtocolStoreMessage(msgPtr, &(msgs[i]));\n\t\tCW_FREE_PROTOCOL_MESSAGE(msgs[i]);\n\t}\n\n\tfor (i = 0; i < infos.radiosCount; i++) {\n\t\tCW_FREE_OBJECT(infos.radios[i].decryptErrorMACAddressList);\n\t}\n\n\tCW_FREE_OBJECT(msgs);\n\tCW_FREE_OBJECT(infos.radios);\n\n\treturn CW_TRUE;\n\n}\n\n/*\nCWBool CWAssembleMsgElemWTPRadioInformation(CWProtocolMessage *msgPtr) {\n    CWProtocolMessage *msgs;\n    CWRadiosInformation infos;\n\n    int len = 0;\n    int i;\n\n    if(msgPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n    CWDebugLog(\"Assemble WTP Radio Info\");\n\n    if(!CWWTPGetRadiosInformation(&infos)) {\n        return CW_FALSE;\n    }\n\n    // create one message element for each radio\n\n    CW_CREATE_ARRAY_ERR(msgs, (infos.radiosCount), CWProtocolMessage, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\n    for(i = 0; i < infos.radiosCount; i++) {\n        // create message\n        CW_CREATE_PROTOCOL_MESSAGE(msgs[i], 5, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n        CWProtocolStore8(&(msgs[i]), infos.radios[i].ID); // ID of the radio\n        CWProtocolStore32(&(msgs[i]), infos.radios[i].type); // type of the radio\n\n        CWDebugLog(\"WTPRadioInformation: %d - %d\", infos.radios[i].ID, infos.radios[i].type);\n\n        if(!(CWAssembleMsgElem(&(msgs[i]), CW_MSG_ELEMENT_WTP_RADIO_INFO_CW_TYPE))) {\n            int j;\n            for(j = i; j >= 0; j--) { CW_FREE_PROTOCOL_MESSAGE(msgs[j]);}\n            CW_FREE_OBJECT(infos.radios);\n            CW_FREE_OBJECT(msgs);\n            return CW_FALSE;\n        }\n\n        len += msgs[i].offset;\n    }\n\n    // return all the messages as one big message\n    CW_CREATE_PROTOCOL_MESSAGE(*msgPtr, len, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\n    for(i = 0; i < infos.radiosCount; i++) {\n        CWProtocolStoreMessage(msgPtr, &(msgs[i]));\n        CW_FREE_PROTOCOL_MESSAGE(msgs[i]);\n    }\n\n    CW_FREE_OBJECT(msgs);\n    CW_FREE_OBJECT(infos.radios);\n\n    return CW_TRUE;\n}\n*/\n\n/*_________________________________________________________________________*/\n/*  *****************************___PARSE___*****************************  */\nCWBool CWParseWTPRadioInformation_FromAC(CWProtocolMessage * msgPtr, int len, char *valPtr)\n{\n\t//CWParseMessageElementStart();\n\n\tCWProtocolRetrieve8(msgPtr);\n\n\tCWProtocolRetrieve8(msgPtr);\n\tCWProtocolRetrieve8(msgPtr);\n\tCWProtocolRetrieve8(msgPtr);\n\t*valPtr = CWProtocolRetrieve8(msgPtr);\n\treturn CW_TRUE;\n\t//CWParseMessageElementEnd();\n}\n\nCWBool CWParseACDescriptor(CWProtocolMessage * msgPtr, int len, CWACInfoValues * valPtr)\n{\n\tint i = 0, theOffset = 0;\n\n\tCWParseMessageElementStart();\n\n\tvalPtr->stations = CWProtocolRetrieve16(msgPtr);\n//  CWDebugLog(\"AC Descriptor Stations: %d\", valPtr->stations);\n\n\tvalPtr->limit = CWProtocolRetrieve16(msgPtr);\n//  CWDebugLog(\"AC Descriptor Limit: %d\", valPtr->limit);\n\n\tvalPtr->activeWTPs = CWProtocolRetrieve16(msgPtr);\n//  CWDebugLog(\"AC Descriptor Active WTPs: %d\", valPtr->activeWTPs);\n\n\tvalPtr->maxWTPs = CWProtocolRetrieve16(msgPtr);\n//  CWDebugLog(\"AC Descriptor Max WTPs: %d\",    valPtr->maxWTPs);\n\n\tvalPtr->security = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"AC Descriptor Security: %d\",    valPtr->security);\n\n\tvalPtr->RMACField = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"AC Descriptor Radio MAC Field: %d\", valPtr->security);\n\n//  valPtr->WirelessField= CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"AC Descriptor Wireless Field: %d\",  valPtr->security);\n\n\tCWProtocolRetrieve8(msgPtr);\t//Reserved\n\n\tvalPtr->DTLSPolicy = CWProtocolRetrieve8(msgPtr);\t// DTLS Policy\n//  CWDebugLog(\"DTLS Policy: %d\",   valPtr->DTLSPolicy);\n\n\tvalPtr->vendorInfos.vendorInfosCount = 0;\n\n\ttheOffset = msgPtr->offset;\n\n\t// see how many vendor ID we have in the message\n\twhile ((msgPtr->offset - oldOffset) < len) {\t// oldOffset stores msgPtr->offset's value at the beginning of this function.\n\t\t// See the definition of the CWParseMessageElementStart() macro.\n\t\tint tmp;\n\n\t\t//CWDebugLog(\"differenza:%d, offset:%d, oldOffset:%d\", (msgPtr->offset-oldOffset), (msgPtr->offset), oldOffset);\n\n\t\t//id = CWProtocolRetrieve32(msgPtr);\n//      CWDebugLog(\"ID: %d\", id); // ID\n\n\t\t//type = CWProtocolRetrieve16(msgPtr);\n//      CWDebugLog(\"TYPE: %d\",type); // type\n\n\t\ttmp = CWProtocolRetrieve16(msgPtr);\n\t\tmsgPtr->offset += tmp;\t// len\n//      CWDebugLog(\"offset %d\", msgPtr->offset);\n\t\tvalPtr->vendorInfos.vendorInfosCount++;\n\t}\n\n\tmsgPtr->offset = theOffset;\n\n\t// actually read each vendor ID\n\tCW_CREATE_ARRAY_ERR(valPtr->vendorInfos.vendorInfos, valPtr->vendorInfos.vendorInfosCount, CWACVendorInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n//  CWDebugLog(\"len %d\", len);\n//  CWDebugLog(\"vendorInfosCount %d\", valPtr->vendorInfos.vendorInfosCount);\n\tfor (i = 0; i < valPtr->vendorInfos.vendorInfosCount; i++) {\n//      CWDebugLog(\"vendorInfosCount %d vs %d\", i, valPtr->vendorInfos.vendorInfosCount);\n\t\t(valPtr->vendorInfos.vendorInfos)[i].vendorIdentifier = CWProtocolRetrieve32(msgPtr);\n\t\t(valPtr->vendorInfos.vendorInfos)[i].type = CWProtocolRetrieve16(msgPtr);\n\t\t(valPtr->vendorInfos.vendorInfos)[i].length = CWProtocolRetrieve16(msgPtr);\n\t\t(valPtr->vendorInfos.vendorInfos)[i].valuePtr =\n\t\t    (int *)(CWProtocolRetrieveRawBytes(msgPtr, (valPtr->vendorInfos.vendorInfos)[i].length));\n\n\t\tif ((valPtr->vendorInfos.vendorInfos)[i].valuePtr == NULL)\n\t\t\treturn CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\n\t\tif ((valPtr->vendorInfos.vendorInfos)[i].length == 4) {\n\t\t\t*((valPtr->vendorInfos.vendorInfos)[i].valuePtr) =\n\t\t\t    ntohl(*((valPtr->vendorInfos.vendorInfos)[i].valuePtr));\n\t\t}\n//      CWDebugLog(\"AC Descriptor Vendor ID: %d\", (valPtr->vendorInfos.vendorInfos)[i].vendorIdentifier);\n//      CWDebugLog(\"AC Descriptor Type: %d\", (valPtr->vendorInfos.vendorInfos)[i].type);\n//      CWDebugLog(\"AC Descriptor Value: %d\", *((valPtr->vendorInfos.vendorInfos)[i].valuePtr));\n\t}\n//  CWDebugLog(\"AC Descriptor Out\");\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseACIPv4List(CWProtocolMessage * msgPtr, int len, ACIPv4ListValues * valPtr)\n{\n\tint i;\n\tCWParseMessageElementStart();\n\n\tif (len == 0 || ((len % 4) != 0))\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Malformed AC IPv4 List Messame Element\");\n\n\tvalPtr->ACIPv4ListCount = (len / 4);\n\n\tCW_CREATE_ARRAY_ERR(valPtr->ACIPv4List, valPtr->ACIPv4ListCount, int,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < valPtr->ACIPv4ListCount; i++) {\n\t\tstruct sockaddr_in addr;\n\t\t(valPtr->ACIPv4List)[i] = CWProtocolRetrieve32(msgPtr);\n\t\tCWDebugLog(\"AC IPv4 List (%d): %d\", i+1, (valPtr->ACIPv4List)[i]);\n\t\taddr.sin_addr.s_addr = (valPtr->ACIPv4List)[i];\n\t\taddr.sin_family = AF_INET;\n\t\taddr.sin_port = 1024;\n\t\tCWUseSockNtop(&addr, CWDebugLog(str);\n\t\t    );\n\t}\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseACIPv6List(CWProtocolMessage * msgPtr, int len, ACIPv6ListValues * valPtr)\n{\n\tint i;\n\tCWParseMessageElementStart();\n\n\tif (len == 0 || ((len % 16) != 0))\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Malformed AC IPv6 List Messame Element\");\n\n\tvalPtr->ACIPv6ListCount = (len / 16);\n\n\tCW_CREATE_ARRAY_ERR(valPtr->ACIPv6List, valPtr->ACIPv6ListCount, struct in6_addr,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < valPtr->ACIPv6ListCount; i++) {\n\t\tstruct sockaddr_in6 addr;\n\n\t\t/*\n\t\t * BUG ML09\n\t\t * 19/10/2009 - Donato Capitella\n\t\t */\n\t\tvoid *ptr;\n\t\tptr = CWProtocolRetrieveRawBytes(msgPtr, 16);\n\t\tCW_COPY_MEMORY(&((valPtr->ACIPv6List)[i]), ptr, 16);\n\t\tCW_FREE_OBJECT(ptr);\n\t\tCW_COPY_MEMORY(&(addr.sin6_addr), &((valPtr->ACIPv6List)[i]), 16);\n\t\taddr.sin6_family = AF_INET6;\n\t\taddr.sin6_port = htons(CW_CONTROL_PORT);\n\n//      CWUseSockNtop(&addr, CWDebugLog(\"AC IPv6 List: %s\",str););\n\t}\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseDeleteStation(CWProtocolMessage * msgPtr, int len)\n{\n\tint Length = 0;\n\tint radioID = 0;\n\tunsigned char *StationMacAddress;\n\n\t//CWParseMessageElementStart();  sostituire al posto delle righe successive quando passerò valPtr alla funzione CWarseAddStation\n\t/*--------------------------------------------------------------------------------------*/\n\tint oldOffset;\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\toldOffset = msgPtr->offset;\n\t/*----------------------------------------------------------------------------------*/\n\n\tradioID = CWProtocolRetrieve8(msgPtr);\n\t//CWDebugLog(\"radio ID %d\",radioID);\n\tLength = CWProtocolRetrieve8(msgPtr);\n\t//CWDebugLog(\"Length of mac address field %d\",Length);\n\tStationMacAddress = (unsigned char *)CWProtocolRetrieveRawBytes(msgPtr, Length);\n\n\tCWDebugLog(\"DEL MAC: %02X:%02X:%02X:%02X:%02X:%02X\", (unsigned char)StationMacAddress[0],\n\t\t   (unsigned char)StationMacAddress[1],\n\t\t   (unsigned char)StationMacAddress[2],\n\t\t   (unsigned char)StationMacAddress[3],\n\t\t   (unsigned char)StationMacAddress[4], (unsigned char)StationMacAddress[5]);\n\n\tunsigned char tmp_mac[7];\n\tmemcpy(tmp_mac + 1, StationMacAddress, 6);\n\n\tCWWTPsend_command_to_hostapd_DEL_ADDR(tmp_mac, 7);\n\n\tCWDebugLog(\"STATION'S MAC ADDRESS TO FORWARD TRAFFIC: %02X:%02X:%02X:%02X:%02X:%02X\",\n\t\t   StationMacAddress[0] & 0xFF,\n\t\t   StationMacAddress[1] & 0xFF,\n\t\t   StationMacAddress[2] & 0xFF,\n\t\t   StationMacAddress[3] & 0xFF, StationMacAddress[4] & 0xFF, StationMacAddress[5] & 0xFF);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseDeleteWLAN(CWProtocolMessage * msgPtr, int len)\n{\n\t//CWParseMessageElementStart();  sostituire al posto delle righe successive quando passerò valPtr alla funzione CWarseAddStation\n\t/*--------------------------------------------------------------------------------------*/\n\tint oldOffset;\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\toldOffset = msgPtr->offset;\n\t/*----------------------------------------------------------------------------------*/\n\n\tCWProtocolRetrieve8(msgPtr);\n\tCWProtocolRetrieve8(msgPtr);\n\n\tunsigned char tmp_ssid[3];\n\n\tCWWTPsend_command_to_hostapd_DEL_WLAN(tmp_ssid, 3);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseAddWLAN(CWProtocolMessage * msgPtr, int len)\n{\n\tCWDebugLog(\"CWParseAddWLAN() 1\");\n\tunsigned char *ssid;\n\tunsigned char tmp_buf[len + 1];\n\n\t//CWParseMessageElementStart();  sostituire al posto delle righe successive quando passerò valPtr alla funzione CWarseAddStation\n\t/*--------------------------------------------------------------------------------------*/\n\tint oldOffset;\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\toldOffset = msgPtr->offset;\n\t/*----------------------------------------------------------------------------------*/\n\tCWDebugLog(\"CWParseAddWLAN() 2\");\n\ttmp_buf[1] = CWProtocolRetrieve8(msgPtr);\n\ttmp_buf[2] = CWProtocolRetrieve8(msgPtr);\n\ttmp_buf[3] = CWProtocolRetrieve8(msgPtr);\n\ttmp_buf[4] = CWProtocolRetrieve8(msgPtr);\n\n\ttmp_buf[5] = CWProtocolRetrieve8(msgPtr);\n\ttmp_buf[6] = CWProtocolRetrieve8(msgPtr);\n\tunsigned short keyLength = CWProtocolRetrieve16(msgPtr);\n\n\tCWDebugLog(\"CWParseAddWLAN() 3, %d, %d\", len, keyLength);\n\n\ttmp_buf[7] = keyLength >> 8;\n\ttmp_buf[8] = keyLength & 0xff;\n\n\tCWDebugLog(\"CWParseAddWLAN() 4\");\n\n\tif (keyLength) {\n\t\tunsigned char *key;\n\t\tCWDebugLog(\"CWParseAddWLAN() 5\");\n\t\tkey = (unsigned char *)CWProtocolRetrieveRawBytes(msgPtr, keyLength);\n\t\tCWDebugLog(\"CWParseAddWLAN() 6 %d\", keyLength);\n\t\tmemcpy(tmp_buf + 9, key, keyLength);\n\t\tCWDebugLog(\"CWParseAddWLAN() 7\");\n\t}\n\n\tCWDebugLog(\"CWParseAddWLAN() 5\");\n\n\ttmp_buf[9 + keyLength] = CWProtocolRetrieve8(msgPtr);\n\tCWDebugLog(\"CWParseAddWLAN() 6\");\n\ttmp_buf[10 + keyLength] = CWProtocolRetrieve8(msgPtr);\n\tCWDebugLog(\"CWParseAddWLAN() 7\");\n\ttmp_buf[11 + keyLength] = CWProtocolRetrieve8(msgPtr);\n\tCWDebugLog(\"CWParseAddWLAN() 8\");\n\ttmp_buf[12 + keyLength] = CWProtocolRetrieve8(msgPtr);\n\ttmp_buf[13 + keyLength] = CWProtocolRetrieve8(msgPtr);\n\ttmp_buf[14 + keyLength] = CWProtocolRetrieve8(msgPtr);\n\n\tCWDebugLog(\"CWParseAddWLAN() 4\");\n\n\ttmp_buf[15 + keyLength] = CWProtocolRetrieve8(msgPtr);\n\n\ttmp_buf[16 + keyLength] = CWProtocolRetrieve8(msgPtr);\t\t\t/* Auth Type */\n\ttmp_buf[17 + keyLength] = gWTPMACMode = CWProtocolRetrieve8(msgPtr);\t/* MAC Mode */\n\ttmp_buf[18 + keyLength] = gWTPTunnelMode = CWProtocolRetrieve8(msgPtr);\t/* Tunnel Mode */\n\ttmp_buf[19 + keyLength] = CWProtocolRetrieve8(msgPtr);\t\t\t/* Suppress SSID */\n\n\tCWDebugLog(\"CWParseAddWLAN() 5\");\n\n\tssid = (unsigned char *)CWProtocolRetrieveRawBytes(msgPtr, len - (19 + keyLength));\n\n\tCWDebugLog(\"CWParseAddWLAN() 6\");\n\n\tmemcpy(tmp_buf + 20 + keyLength, ssid, len - 19 - keyLength);\n\n\tCWDebugLog(\"CWParseAddWLAN() 7\");\n\t\n\tCWWTPsend_command_to_hostapd_ADD_WLAN(tmp_buf, len + 1);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseAddStation(CWProtocolMessage * msgPtr, int len)\n{\n\tint Length;\n\tint radioID;\n\tunsigned char *StationMacAddress;\n\n\t//CWParseMessageElementStart();  sostituire al posto delle righe successive quando passerò valPtr alla funzione CWarseAddStation\n\t/*--------------------------------------------------------------------------------------*/\n\tint oldOffset;\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\toldOffset = msgPtr->offset;\n\t/*----------------------------------------------------------------------------------*/\n\n\tradioID = CWProtocolRetrieve8(msgPtr);\n\tCWDebugLog(\"radio ID %d\",radioID);\n\tLength = CWProtocolRetrieve8(msgPtr);\n\tCWDebugLog(\"Length of mac address field %d\",Length);\n\tStationMacAddress = (unsigned char *)CWProtocolRetrieveRawBytes(msgPtr, Length);\n\n\tCWDebugLog(\"ADD MAC: %02X:%02X:%02X:%02X:%02X:%02X\", (unsigned char)StationMacAddress[0],\n\t\t   (unsigned char)StationMacAddress[1],\n\t\t   (unsigned char)StationMacAddress[2],\n\t\t   (unsigned char)StationMacAddress[3],\n\t\t   (unsigned char)StationMacAddress[4], (unsigned char)StationMacAddress[5]);\n\n\tunsigned char tmp_mac[7];\n\tmemcpy(tmp_mac + 1, StationMacAddress, 6);\n\n\tCWWTPsend_command_to_hostapd_SET_ADDR(tmp_mac, 7);\n\n\tCWDebugLog(\"STATION'S MAC ADDRESS TO FORWARD TRAFFIC: %02X:%02X:%02X:%02X:%02X:%02X\",\n\t\t   StationMacAddress[0] & 0xFF,\n\t\t   StationMacAddress[1] & 0xFF,\n\t\t   StationMacAddress[2] & 0xFF,\n\t\t   StationMacAddress[3] & 0xFF, StationMacAddress[4] & 0xFF, StationMacAddress[5] & 0xFF);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseCWControlIPv4Addresses(CWProtocolMessage * msgPtr, int len, CWProtocolIPv4NetworkInterface * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->addr.sin_addr.s_addr = htonl(CWProtocolRetrieve32(msgPtr));\n\tvalPtr->addr.sin_family = AF_INET;\n\tvalPtr->addr.sin_port = htons(CW_CONTROL_PORT);\n\n\tCWUseSockNtop((&(valPtr->addr)), CWDebugLog(\"Interface Address: %s\", str);\n\t    );\n\n\tvalPtr->WTPCount = CWProtocolRetrieve16(msgPtr);\n\tCWDebugLog(\"WTP Count: %d\", valPtr->WTPCount);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseCWControlIPv6Addresses(CWProtocolMessage * msgPtr, int len, CWProtocolIPv6NetworkInterface * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tCW_COPY_MEMORY(&(valPtr->addr.sin6_addr), CWProtocolRetrieveRawBytes(msgPtr, 16), 16);\n\tvalPtr->addr.sin6_family = AF_INET6;\n\tvalPtr->addr.sin6_port = htons(CW_CONTROL_PORT);\n\n\tCWUseSockNtop((&(valPtr->addr)), CWDebugLog(\"Interface Address: %s\", str);\n\t    );\n\n\tvalPtr->WTPCount = CWProtocolRetrieve16(msgPtr);\n//  CWDebugLog(\"WTP Count: %d\", valPtr->WTPCount);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseCWTimers(CWProtocolMessage * msgPtr, int len, CWProtocolConfigureResponseValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->discoveryTimer = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"Discovery Timer: %d\", valPtr->discoveryTimer);\n\tvalPtr->echoRequestTimer = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"Echo Timer: %d\", valPtr->echoRequestTimer);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseDecryptErrorReportPeriod(CWProtocolMessage * msgPtr, int len, WTPDecryptErrorReportValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->radioID = CWProtocolRetrieve8(msgPtr);\n\tvalPtr->reportInterval = CWProtocolRetrieve16(msgPtr);\n//  CWDebugLog(\"Decrypt Error Report Period: %d - %d\", valPtr->radioID, valPtr->reportInterval);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseIdleTimeout(CWProtocolMessage * msgPtr, int len, CWProtocolConfigureResponseValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->idleTimeout = CWProtocolRetrieve32(msgPtr);\n//  CWDebugLog(\"Idle Timeout: %d\", valPtr->idleTimeout);\n\n\tCWParseMessageElementEnd();\n}\n\nCWBool CWParseWTPFallback(CWProtocolMessage * msgPtr, int len, CWProtocolConfigureResponseValues * valPtr)\n{\n\tCWParseMessageElementStart();\n\n\tvalPtr->fallback = CWProtocolRetrieve8(msgPtr);\n//  CWDebugLog(\"WTP Fallback: %d\", valPtr->fallback);\n\n\tCWParseMessageElementEnd();\n}\n\nvoid CWWTPResetRebootStatistics(WTPRebootStatisticsInfo * rebootStatistics)\n{\n\trebootStatistics->rebootCount = 0;\n\trebootStatistics->ACInitiatedCount = 0;\n\trebootStatistics->linkFailurerCount = 0;\n\trebootStatistics->SWFailureCount = 0;\n\trebootStatistics->HWFailuireCount = 0;\n\trebootStatistics->otherFailureCount = 0;\n\trebootStatistics->unknownFailureCount = 0;\n\trebootStatistics->lastFailureType = NOT_SUPPORTED;\n}\n"
  },
  {
    "path": "WTPProtocol.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_WTPProtocol_HEADER__\n#define __CAPWAP_WTPProtocol_HEADER__\n\n/*_____________________________________________________*/\n/*  *******************___TYPES___*******************  */\ntypedef struct {\n\tint ACIPv4ListCount;\n\tint *ACIPv4List;\n} ACIPv4ListValues;\n\ntypedef struct {\n\tint ACIPv6ListCount;\n\tstruct in6_addr *ACIPv6List;\n} ACIPv6ListValues;\n\ntypedef struct {\n\tint stations;\n\tint limit;\n\tint activeWTPs;\n\tint maxWTPs;\n\tCWAuthSecurity security;\n\tint RMACField;\n//  int WirelessField;\n\tint DTLSPolicy;\n\tCWACVendorInfos vendorInfos;\n\tchar *name;\n\tCWProtocolIPv4NetworkInterface *IPv4Addresses;\n\tint IPv4AddressesCount;\n\tCWProtocolIPv6NetworkInterface *IPv6Addresses;\n\tint IPv6AddressesCount;\n\tACIPv4ListValues ACIPv4ListInfo;\n\tACIPv6ListValues ACIPv6ListInfo;\n\tCWNetworkLev4Address preferredAddress;\n\tCWNetworkLev4Address incomingAddress;\n} CWACInfoValues;\n\ntypedef struct {\n\tCWACInfoValues ACInfoPtr;\n\tCWProtocolResultCode code;\n\tACIPv4ListValues ACIPv4ListInfo;\n\tACIPv6ListValues ACIPv6ListInfo;\n} CWProtocolJoinResponseValues;\n\ntypedef struct {\n\tACIPv4ListValues ACIPv4ListInfo;\n\tACIPv6ListValues ACIPv6ListInfo;\n\tint discoveryTimer;\n\tint echoRequestTimer;\n\tint radioOperationalInfoCount;\n\tCWRadioOperationalInfoValues *radioOperationalInfo;\n\tWTPDecryptErrorReport radiosDecryptErrorPeriod;\n\tint idleTimeout;\n\tint fallback;\n\tvoid *bindingValues;\n} CWProtocolConfigureResponseValues;\n\ntypedef struct {\n\tvoid *bindingValues;\n\t/*Update 2009:\n\t   add new non-binding specific values */\n\tvoid *protocolValues;\n} CWProtocolConfigurationUpdateRequestValues;\n\n/*__________________________________________________________*/\n/*  *******************___PROTOTYPES___*******************  */\nCWBool CWAssembleMsgElemACName(CWProtocolMessage * msgPtr);\t// 4\nCWBool CWAssembleMsgElemACNameWithIndex(CWProtocolMessage * msgPtr);\t// 5\nCWBool CWAssembleMsgElemDataTransferData(CWProtocolMessage * msgPtr, int data_type);\t//13\nCWBool CWAssembleMsgElemDiscoveryType(CWProtocolMessage * msgPtr);\t//20\nCWBool CWAssembleMsgElemDuplicateIPv4Address(CWProtocolMessage * msgPtr);\t//21\nCWBool CWAssembleMsgElemLocationData(CWProtocolMessage * msgPtr);\t//27\nCWBool CWAssembleMsgElemStatisticsTimer(CWProtocolMessage * msgPtr);\t//33\nCWBool CWAssembleMsgElemWTPBoardData(CWProtocolMessage * msgPtr);\t//35\nCWBool CWAssembleMsgElemWTPDescriptor(CWProtocolMessage * msgPtr);\t//36\nCWBool CWAssembleMsgElemWTPFrameTunnelMode(CWProtocolMessage * msgPtr);\t//38\nCWBool CWAssembleMsgElemWTPIPv4Address(CWProtocolMessage * msgPtr);\t//39\nCWBool CWAssembleMsgElemWTPMACType(CWProtocolMessage * msgPtr);\t//40\nCWBool CWAssembleMsgElemWTPRadioInformation(CWProtocolMessage * msgPtr);\t//1048\nCWBool CWAssembleMsgElemSupportedRates(CWProtocolMessage * msgPtr);\t//1040\nCWBool CWAssembleMsgElemMultiDomainCapability(CWProtocolMessage * msgPtr);\t//1032\nCWBool CWAssembleMsgElemWTPName(CWProtocolMessage * msgPtr);\t//41\nCWBool CWAssembleMsgElemWTPOperationalStatistics(CWProtocolMessage * msgPtr, int radio);\t//42\nCWBool CWAssembleMsgElemWTPRadioStatistics(CWProtocolMessage * msgPtr, int radio);\t//43\nCWBool CWAssembleMsgElemWTPRebootStatistics(CWProtocolMessage * msgPtr);\t//44\n//CWBool CWAssembleMsgElemWTPStaticIPInfo(CWProtocolMessage *msgPtr);           //45\n\n//CWBool CWAssembleMsgElemWTPRadioInformation(CWProtocolMessage *msgPtr);\n\n//---------------------------------------------------------/\nCWBool CWParseACDescriptor(CWProtocolMessage * msgPtr, int len, CWACInfoValues * valPtr);\t// 1\nCWBool CWParseACIPv4List(CWProtocolMessage * msgPtr, int len, ACIPv4ListValues * valPtr);\t// 2\nCWBool CWParseACIPv6List(CWProtocolMessage * msgPtr, int len, ACIPv6ListValues * valPtr);\t// 3\nCWBool CWParseAddStation(CWProtocolMessage * msgPtr, int len);\t// 8\nCWBool CWParseDeleteStation(CWProtocolMessage * msgPtr, int len);\t// 18\nCWBool CWParseCWControlIPv4Addresses(CWProtocolMessage * msgPtr, int len, CWProtocolIPv4NetworkInterface * valPtr);\t//10\nCWBool CWParseCWControlIPv6Addresses(CWProtocolMessage * msgPtr, int len, CWProtocolIPv6NetworkInterface * valPtr);\t//11\nCWBool CWParseCWTimers(CWProtocolMessage * msgPtr, int len, CWProtocolConfigureResponseValues * valPtr);\t//12\nCWBool CWParseDecryptErrorReportPeriod(CWProtocolMessage * msgPtr, int len, WTPDecryptErrorReportValues * valPtr);\t//16\nCWBool CWParseIdleTimeout(CWProtocolMessage * msgPtr, int len, CWProtocolConfigureResponseValues * valPtr);\t//26\nCWBool CWParseWTPFallback(CWProtocolMessage * msgPtr, int len, CWProtocolConfigureResponseValues * valPtr);\t//37\nCWBool CWParseWTPRadioInformation_FromAC(CWProtocolMessage * msgPtr, int len, char *valPtr);\t// 1048\n\n//si trova in CWProtocol.h\n//CWBool CWParseACName(CWProtocolMessage *msgPtr, int len, char **valPtr);                      // 4\n\n//---------------------------------------------------------/\nvoid CWWTPResetRebootStatistics(WTPRebootStatisticsInfo * rebootStatistics);\n\nint CWWTPGetDiscoveryType(void);\nint CWWTPGetMaxRadios(void);\nint CWWTPGetRadiosInUse(void);\nCWBool CWWTPGetEncCapabilities(CWWTPEncryptCaps * encc);\nvoid CWWTPDestroyEncCapabilities(CWWTPEncryptCaps * encc);\nCWBool CWWTPGetBoardData(CWWTPVendorInfos * valPtr);\nCWBool CWWTPGetVendorInfos(CWWTPVendorInfos * valPtr);\nint CWWTPGetMACType(void);\nchar *CWWTPGetLocation(void);\nint CWWTPGetSessionID(void);\nint CWWTPGetIPv4Address(void);\nint CWWTPGetIPv4StatusDuplicate(void);\nint CWWTPGetIPv6StatusDuplicate(void);\nchar *CWWTPGetName(void);\nCWBool CWWTPGetRadiosInformation(CWRadiosInformation * valPtr);\nint CWWTPGetACIndex();\nchar *CWWTPGetACName();\nint CWWTPGetFrameTunnelMode();\nCWBool CWGetWTPRadiosOperationalState(int radioID, CWRadiosOperationalInfo * valPtr);\nCWBool CWAssembleMsgElemDecryptErrorReport(CWProtocolMessage * msgPtr, int radioID);\nCWBool CWAssembleMsgElemDuplicateIPv6Address(CWProtocolMessage * msgPtr);\nCWBool CWAssembleMsgElemVendorSpecificPayload(CWProtocolMessage * msgPtr);\n\nCWBool CWParseAddWLAN(CWProtocolMessage * msgPtr, int len);\nCWBool CWParseDeleteWLAN(CWProtocolMessage * msgPtr, int len);\n\n//---------------------------------------------------------/\nvoid CWWTPDestroyVendorInfos(CWWTPVendorInfos * valPtr);\n\n#endif\n"
  },
  {
    "path": "WTPProtocol_User.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#define MAC_ADDR_LEN        6\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n__inline__ int CWWTPGetDiscoveryType()\n{\n\treturn CW_MSG_ELEMENT_DISCOVERY_TYPE_CONFIGURED;\n}\n\n__inline__ int CWWTPGetMaxRadios()\n{\n\treturn 1;\n}\n\n__inline__ int CWWTPGetRadiosInUse()\n{\n\t/*for (i=0; i<gRadiosInfo.radioCount; i++)\n\t   {\n\t   if((gRadiosInfo.radiosInfo[i].operationalState) == ENABLED)\n\t   active++;\n\t   }\n\t   return active;\n\t */\n\treturn gRadiosInfo.radioCount;\n}\n\nCWBool CWWTPGetEncCapabilities(CWWTPEncryptCaps * encc)\n{\n\tif (encc == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tencc->encryptCapsCount = 1;\n\tCW_CREATE_ARRAY_ERR((encc->encryptCaps), encc->encryptCapsCount, CWWTPEncryptCapValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t(encc->encryptCaps)[0].WBID = 1;\n\t(encc->encryptCaps)[0].encryptionCapabilities = 2569;\n\n\treturn CW_TRUE;\n}\n\nvoid CWWTPDestroyEncCapabilities(CWWTPEncryptCaps * encc)\n{\n\tif (encc == NULL)\n\t\treturn;\n\n\tCW_FREE_OBJECT(encc->encryptCaps);\n}\n\nCWBool CWWTPGetBoardData(CWWTPVendorInfos * valPtr)\n{\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tvalPtr->vendorInfosCount = 2;\t// we fill 2 information (just the required ones)\n\tCW_CREATE_ARRAY_ERR((valPtr->vendorInfos), valPtr->vendorInfosCount, CWWTPVendorInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t// my vendor identifier (IANA assigned \"SMI Network Management Private Enterprise Code\")\n\t(valPtr->vendorInfos)[0].vendorIdentifier = 23456;\n\t(valPtr->vendorInfos)[0].type = CW_WTP_MODEL_NUMBER;\n\t(valPtr->vendorInfos)[0].length = sizeof(long int);\t// just one int\n\tCW_CREATE_OBJECT_SIZE_ERR((((valPtr->vendorInfos)[0]).valuePtr), (valPtr->vendorInfos)[0].length,\n\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*(int *)(((valPtr->vendorInfos)[0]).valuePtr) = 123456;\t// MODEL NUMBER\n\n\t// my vendor identifier (IANA assigned \"SMI Network Management Private Enterprise Code\")\n\t(valPtr->vendorInfos)[1].vendorIdentifier = 23456;\n\t(valPtr->vendorInfos)[1].type = CW_WTP_SERIAL_NUMBER;\n\t(valPtr->vendorInfos)[1].length = sizeof(long int);\t// just one int\n\tCW_CREATE_OBJECT_SIZE_ERR((((valPtr->vendorInfos)[1]).valuePtr), (valPtr->vendorInfos)[1].length,\n\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*(int *)(((valPtr->vendorInfos)[1]).valuePtr) = 123456;\t// SERIAL NUMBER\n\n\treturn CW_TRUE;\n}\n\nCWBool CWWTPGetVendorInfos(CWWTPVendorInfos * valPtr)\n{\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tvalPtr->vendorInfosCount = 3;\t// we fill 3 information (just the required ones)\n\tCW_CREATE_ARRAY_ERR((valPtr->vendorInfos), valPtr->vendorInfosCount, CWWTPVendorInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t// my vendor identifier (IANA assigned \"SMI Network Management Private Enterprise Code\")\n\t(valPtr->vendorInfos)[0].vendorIdentifier = 23456;\n\t(valPtr->vendorInfos)[0].type = CW_WTP_HARDWARE_VERSION;\n\t(valPtr->vendorInfos)[0].length = sizeof(long int);\t// just one int\n\tCW_CREATE_OBJECT_SIZE_ERR((((valPtr->vendorInfos)[0]).valuePtr), (valPtr->vendorInfos)[0].length,\n\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*(int *)(((valPtr->vendorInfos)[0]).valuePtr) = 123456;\t// HW version\n\n\t// my vendor identifier (IANA assigned \"SMI Network Management Private Enterprise Code\")\n\t((valPtr->vendorInfos)[1]).vendorIdentifier = 23456;\n\t((valPtr->vendorInfos)[1]).type = CW_WTP_SOFTWARE_VERSION;\n\t((valPtr->vendorInfos)[1]).length = sizeof(long int);\t// just one int\n\tCW_CREATE_OBJECT_SIZE_ERR((((valPtr->vendorInfos)[1]).valuePtr), (valPtr->vendorInfos)[1].length,\n\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*(int *)(((valPtr->vendorInfos)[1]).valuePtr) = 12347;\t// SW version\n\n\t// my vendor identifier (IANA assigned \"SMI Network Management Private Enterprise Code\")\n\t(valPtr->vendorInfos)[2].vendorIdentifier = 23456;\n\t(valPtr->vendorInfos)[2].type = CW_BOOT_VERSION;\n\t(valPtr->vendorInfos)[2].length = sizeof(long int);\t// just one int\n\tCW_CREATE_OBJECT_SIZE_ERR((((valPtr->vendorInfos)[2]).valuePtr), (valPtr->vendorInfos)[2].length,\n\t\t\t\t  return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\t*(int *)(((valPtr->vendorInfos)[2]).valuePtr) = 1234568;\t// Boot version\n\n\treturn CW_TRUE;\n}\n\n__inline__ void CWWTPDestroyVendorInfos(CWWTPVendorInfos * valPtr)\n{\n\tint i;\n\n\tif (valPtr == NULL)\n\t\treturn;\n\n\tfor (i = 0; i < valPtr->vendorInfosCount; i++) {\n\t\tCW_FREE_OBJECT((valPtr->vendorInfos)[i].valuePtr);\n\t}\n\n\tCW_FREE_OBJECT(valPtr->vendorInfos);\n}\n\n__inline__ int CWWTPGetFrameTunnelMode()\n{\n\t//it may be also 802.3_FrameTunnelMode - NativeFrameTunnelMode - All\n\n#ifdef SOFTMAC\n\treturn CW_NATIVE_BRIDGING | CW_802_DOT_3_BRIDGING;\n#else\n\treturn CW_LOCAL_BRIDGING;\n#endif\n\n}\n\n__inline__ int CWWTPGetMACType()\n{\n\n#ifdef SOFTMAC\n\treturn CW_BOTH;\n#else\n\treturn CW_LOCAL_MAC;\n#endif\n\n}\n\n__inline__ char *CWWTPGetLocation()\n{\n\treturn gWTPLocation;\n}\n\n__inline__ int CWWTPGetSessionID()\n{\n\treturn CWRandomIntInRange(0, INT_MAX);\n}\n\n__inline__ int CWWTPGetIPv4Address()\n{\n\tstruct sockaddr_in myAddr;\n\tunsigned int len = sizeof(myAddr);\n\n\t//CWDebugLog(\"WTPGetIPv4Address\");\n\n\t/* assume the socket is connected */\n\tgetsockname(gWTPSocket, (struct sockaddr *)&myAddr, &len);\n\n\treturn ntohl(myAddr.sin_addr.s_addr);\t// TO-DO: this is garbage if we are an IPv6 client\n}\n\n__inline__ void CWWTPGetIPv6Address(struct sockaddr_in6 *myAddr)\n{\n\n\tunsigned int len = sizeof(*myAddr);\n\n\t/* assume the socket is connected */\n\tgetsockname(gWTPSocket, (struct sockaddr *)myAddr, &len);\n}\n\n__inline__ int CWWTPGetIPv4StatusDuplicate()\n{\n\treturn gIPv4StatusDuplicate;\n}\n\n__inline__ int CWWTPGetIPv6StatusDuplicate()\n{\n\treturn gIPv6StatusDuplicate;\n}\n\n__inline__ char *CWWTPGetName()\n{\n\treturn gWTPName;\n}\n\n/*CWBool CWWTPGetRadiosInformation(CWRadiosInformation *valPtr) {\n    if(valPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n    valPtr->radiosCount = 2;\n\n    CW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWRadioInformationValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\n    (valPtr->radios)[0].ID = 0; // first radio\n    (valPtr->radios)[0].type = CW_802_DOT_11b;\n\n    (valPtr->radios)[1].ID = 1; // second radio\n    (valPtr->radios)[1].type = CW_802_DOT_11b;\n\n    return CW_TRUE;\n}\n*/\n\n/* L'AC ha la funzione ridefinita */\nCWBool CWGetWTPRadiosAdminState(CWRadiosAdminInfo * valPtr)\n{\n\tint i;\n\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tvalPtr->radiosCount = gRadiosInfo.radioCount;\n\n\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWRadioAdminInfoValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tfor (i = 0; i < gRadiosInfo.radioCount; i++) {\n\t\t(valPtr->radios)[i].ID = gRadiosInfo.radiosInfo[i].radioID;\t// first radio\n\t\t(valPtr->radios)[i].state = gRadiosInfo.radiosInfo[i].adminState;\n\t\t(valPtr->radios)[i].cause = gRadiosInfo.radiosInfo[i].adminCause;\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWGetWTPRadiosOperationalState(int radioID, CWRadiosOperationalInfo * valPtr)\n{\n\tint i;\n\tCWBool found = CW_FALSE;\n\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tif (radioID < 0) {\n\n\t\tvalPtr->radiosCount = gRadiosInfo.radioCount;\n\n\t\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWRadioOperationalInfoValues,\n\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tfor (i = 0; i < gRadiosInfo.radioCount; i++) {\n\t\t\t(valPtr->radios)[i].ID = gRadiosInfo.radiosInfo[i].radioID;\n\t\t\t(valPtr->radios)[i].state = gRadiosInfo.radiosInfo[i].operationalState;\n\t\t\t(valPtr->radios)[i].cause = gRadiosInfo.radiosInfo[i].operationalCause;\n\t\t}\n\t\treturn CW_TRUE;\n\t} else {\n\t\tfor (i = 0; i < gRadiosInfo.radioCount; i++) {\n\t\t\tif (gRadiosInfo.radiosInfo[i].radioID == radioID) {\n\t\t\t\tfound = CW_TRUE;\n\t\t\t\tvalPtr->radiosCount = 1;\n\t\t\t\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWRadioOperationalInfoValues,\n\t\t\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\t(valPtr->radios)[0].ID = gRadiosInfo.radiosInfo[i].radioID;\n\t\t\t\t(valPtr->radios)[0].state = gRadiosInfo.radiosInfo[i].operationalState;\n\t\t\t\t(valPtr->radios)[0].cause = gRadiosInfo.radiosInfo[i].operationalCause;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn found;\n\t}\n}\n\nCWBool CWGetDecryptErrorReport(int radioID, CWDecryptErrorReportInfo * valPtr)\n{\n\tint i;\n\tCWBool found = CW_FALSE;\n\n\t/*\n\t   CWMACAddress add, add2;\n\t   for(i=0; i<6; i++) add[i]=i;\n\t   for(i=0; i<6; i++) add2[i]=99;\n\t   CWListElement elem,elem2;\n\t   elem.data = add;\n\t   elem.next = &elem2;\n\t   elem2.data = &add2;\n\t   elem2.next = NULL;\n\t   gRadiosInfo.radiosInfo[0].decryptErrorMACAddressList = &elem;\n\t */\n\n\tif (valPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tvalPtr->radios = NULL;\n\n\tif (radioID < 0) {\n\n\t\tvalPtr->radiosCount = gRadiosInfo.radioCount;\n\n\t\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWDecryptErrorReportValues,\n\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\n\t\tfor (i = 0; i < gRadiosInfo.radioCount; i++) {\n\t\t\t(valPtr->radios)[i].ID = gRadiosInfo.radiosInfo[i].radioID;\n\t\t\t(valPtr->radios)[i].numEntries =\n\t\t\t    CWCountElementInList(gRadiosInfo.radiosInfo[i].decryptErrorMACAddressList);\n\t\t\t(valPtr->radios[i]).decryptErrorMACAddressList = NULL;\n\t\t\tCW_CREATE_ARRAY_ERR((valPtr->radios[i]).decryptErrorMACAddressList,\n\t\t\t\t\t    (valPtr->radios[i]).numEntries, CWMACAddress,\n\t\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tint j;\n\t\t\tCWListElement *temp;\n\t\t\ttemp = gRadiosInfo.radiosInfo[i].decryptErrorMACAddressList;\n\t\t\tfor (j = 0; j < (valPtr->radios[i]).numEntries; j++) {\n\t\t\t\tCW_COPY_MEMORY((valPtr->radios[i]).decryptErrorMACAddressList[j], temp->data,\n\t\t\t\t\t       sizeof(CWMACAddress));\n\t\t\t\ttemp = temp->next;\n\t\t\t}\n\t\t}\n\t\treturn CW_TRUE;\n\t} else {\n\t\tfor (i = 0; i < gRadiosInfo.radioCount; i++) {\n\t\t\tif (gRadiosInfo.radiosInfo[i].radioID == radioID) {\n\t\t\t\tfound = CW_TRUE;\n\t\t\t\tvalPtr->radiosCount = 1;\n\t\t\t\tCW_CREATE_ARRAY_ERR(valPtr->radios, valPtr->radiosCount, CWDecryptErrorReportValues,\n\t\t\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\t(valPtr->radios)[0].ID = gRadiosInfo.radiosInfo[i].radioID;\n\t\t\t\t(valPtr->radios)[0].numEntries =\n\t\t\t\t    CWCountElementInList(gRadiosInfo.radiosInfo[i].decryptErrorMACAddressList);\n\t\t\t\t(valPtr->radios[0]).decryptErrorMACAddressList = NULL;\n\t\t\t\tCW_CREATE_ARRAY_ERR((valPtr->radios[0]).decryptErrorMACAddressList,\n\t\t\t\t\t\t    (valPtr->radios[0]).numEntries, CWMACAddress,\n\t\t\t\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t\t    );\n\t\t\t\tint j;\n\t\t\t\tCWListElement *temp;\n\t\t\t\ttemp = gRadiosInfo.radiosInfo[0].decryptErrorMACAddressList;\n\t\t\t\tfor (j = 0; j < (valPtr->radios[0]).numEntries; j++) {\n\t\t\t\t\tCW_COPY_MEMORY((valPtr->radios[0]).decryptErrorMACAddressList[j], temp->data,\n\t\t\t\t\t\t       6);\n\t\t\t\t\ttemp = temp->next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn found;\n\t}\n}\n\nint CWWTPGetACIndex()\n{\n\treturn 1;\t\t//valore predefinito\n}\n\nchar *CWWTPGetACName()\n{\n\treturn gACInfoPtr->name;\n}\n\nint CWWTPGetStatisticsTimer()\n{\n\treturn gWTPStatisticsTimer;\n}\n\nCWBool CWWTPGetACNameWithIndex(CWACNamesWithIndex * ACsInfo)\n{\n\tif (ACsInfo == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tACsInfo->count = 2;\n\n\tCW_CREATE_ARRAY_ERR(ACsInfo->ACNameIndex, ACsInfo->count, CWACNameWithIndexValues,\n\t\t\t    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t(ACsInfo->ACNameIndex)[0].index = 0;\t// first radio\n\tCW_CREATE_STRING_FROM_STRING_ERR((ACsInfo->ACNameIndex)[0].ACName, \"ACPrimary\",\n\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\t(ACsInfo->ACNameIndex)[1].index = 1;\t// first radio\n\tCW_CREATE_STRING_FROM_STRING_ERR((ACsInfo->ACNameIndex)[1].ACName, \"ACSecondary\",\n\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );;\n\n\treturn CW_TRUE;\n}\n\nint getInterfaceMacAddr(char *interface, unsigned char *macAddr)\n{\n\tstruct ifreq ethreq;\n\tint i, sock;\n\n\tsock = socket(AF_INET, SOCK_DGRAM, 0);\n\tif (sock < 0) {\n\t\tCWLog(\"Error Creating Socket for ioctl\");\n\t\treturn -1;\n\t}\n\n\tmemset(&ethreq, 0, sizeof(ethreq));\n\tstrncpy(ethreq.ifr_name, interface, IFNAMSIZ);\n\tif (ioctl(sock, SIOCGIFHWADDR, &ethreq) == -1) {\n\t\treturn -1;\n\t}\n\n\tfor (i = 0; i < MAC_ADDR_LEN; i++) {\n\t\tmacAddr[i] = (unsigned char)ethreq.ifr_hwaddr.sa_data[i];\n\t}\n\n\treturn 0;\n}\n\nint initWTPSessionID(unsigned char *sessionID)\n{\n\tunsigned char macAddr0[MAC_ADDR_LEN];\n\tunsigned char macAddr1[MAC_ADDR_LEN];\n\tint i, randomInteger;\n\tunsigned char *buffer = sessionID;\n\n\tgetInterfaceMacAddr(gEthInterfaceName, macAddr0);\n\tgetInterfaceMacAddr(gRadioInterfaceName_0, macAddr1);\n\trandomInteger = CWRandomIntInRange(0, INT_MAX);\n\trandomInteger = htonl(randomInteger);\n\n\tCW_COPY_MEMORY(sessionID, macAddr0, MAC_ADDR_LEN);\n\tCW_COPY_MEMORY(&(sessionID[MAC_ADDR_LEN]), macAddr1, MAC_ADDR_LEN);\n\tCW_COPY_MEMORY(&(sessionID[MAC_ADDR_LEN + MAC_ADDR_LEN]), &(randomInteger), 4);\n\n\tfor (i = 0; i < 16; i++) {\n\t\tif (i % 16 == 0)\n\t\t\tprintf(\"\\n%04x:   \", i);\n\t\tprintf(\"%02x:\", buffer[i]);\n\t}\n\tprintf(\"\\n\");\n\n\treturn 0;\n}\n"
  },
  {
    "path": "WTPRetransmission.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nvoid CWResetPendingMsgBox(CWPendingRequestMessage * pendingRequestMsgs)\n{\n\tpendingRequestMsgs->msgType = UNUSED_MSG_TYPE;\n\tpendingRequestMsgs->seqNum = 0;\n\tpendingRequestMsgs->retransmission = 0;\n\tpendingRequestMsgs->timer_sec = 0;\n\tpendingRequestMsgs->timer_hdl = NULL;\n\n\tCW_FREE_OBJECT(pendingRequestMsgs->timer_arg);\n\tpendingRequestMsgs->timer_arg = NULL;\n\n\ttimer_rem(pendingRequestMsgs->timer, NULL);\n\n\tint i;\n\tfor (i = 0; i < (pendingRequestMsgs->fragmentsNum); i++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE((pendingRequestMsgs->msgElems)[i]);\n\t}\n\tCW_FREE_OBJECT(pendingRequestMsgs->msgElems);\n\n\tpendingRequestMsgs->fragmentsNum = 0;\n\n\treturn;\n}\n\nint CWFindFreePendingMsgBox(CWPendingRequestMessage * pendingRequestMsgs, const int length)\n{\n\tint k;\n\n\tfor (k = 0; k < length; k++) {\n\t\tif (pendingRequestMsgs[k].msgType == UNUSED_MSG_TYPE) {\n\t\t\tCWResetPendingMsgBox(pendingRequestMsgs + k);\n\t\t\treturn k;\n\t\t}\n\t}\n\treturn -1;\n}\n\nCWBool CWUpdatePendingMsgBox(CWPendingRequestMessage * pendingRequestMsgs,\n\t\t\t     unsigned char msgType,\n\t\t\t     int seqNum,\n\t\t\t     int timer_sec,\n\t\t\t     CWTimerArg timer_arg,\n\t\t\t     void (*timer_hdl) (CWTimerArg),\n\t\t\t     int retransmission, CWProtocolMessage * msgElems, int fragmentsNum)\n{\n\n\tif (pendingRequestMsgs == NULL)\n\t\treturn CW_FALSE;\n\tif (pendingRequestMsgs->msgType != UNUSED_MSG_TYPE)\n\t\treturn CW_TRUE;\n\n\tpendingRequestMsgs->msgType = msgType;\n\tpendingRequestMsgs->seqNum = seqNum;\n\tpendingRequestMsgs->retransmission = retransmission;\n\tpendingRequestMsgs->msgElems = msgElems;\n\tpendingRequestMsgs->fragmentsNum = fragmentsNum;\n\tpendingRequestMsgs->timer_sec = timer_sec;\n\tpendingRequestMsgs->timer_hdl = timer_hdl;\n\tpendingRequestMsgs->timer_arg = timer_arg;\n\tif ((pendingRequestMsgs->timer = timer_add(timer_sec, 0, timer_hdl, timer_arg))) {\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\nint CWFindPendingRequestMsgsBox(CWPendingRequestMessage * pendingRequestMsgs,\n\t\t\t\tconst int length, const int msgType, const int seqNum)\n{\n\n\tif (pendingRequestMsgs == NULL)\n\t\treturn -1;\n\t/* CWDebugLog(\"### TYPE = %d   SEQNUM = %d\", msgType, seqNum); */\n\tint k;\n\tfor (k = 0; k < length; k++) {\n\t\t/* CWDebugLog(\"### K = %d   TYPE = %d   SEQNUM = %d\", k, pendingRequestMsgs[k].msgType, pendingRequestMsgs[k].seqNum); */\n\t\tif ((pendingRequestMsgs[k].seqNum == seqNum) && (pendingRequestMsgs[k].msgType == msgType)) {\n\n\t\t\ttimer_rem(pendingRequestMsgs[k].timer, NULL);\n\t\t\treturn k;\n\t\t}\n\t}\n\treturn -1;\n\n}\n\nint CWSendPendingRequestMessage(CWPendingRequestMessage * pendingRequestMsgs, CWProtocolMessage * messages,\n\t\t\t\tint fragmentsNum)\n{\n\tint pendingReqIndex = -1;\n\n\tif (messages == NULL || fragmentsNum < 0) {\n\t\treturn -1;\n\t}\n\n\tpendingReqIndex = CWFindFreePendingMsgBox(pendingRequestMsgs, MAX_PENDING_REQUEST_MSGS);\n\n\tif (pendingReqIndex < 0) {\n\t\treturn -1;\n\t}\n\n\tint i;\n\tfor (i = 0; i < fragmentsNum; i++) {\n#ifdef CW_NO_DTLS\n\t\tif (!CWNetworkSendUnsafeConnected(gWTPSocket, messages[i].msg, messages[i].offset)) {\n#else\n\t\tif (!CWSecuritySend(gWTPSession, messages[i].msg, messages[i].offset)) {\n#endif\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\treturn pendingReqIndex;\n}\n"
  },
  {
    "path": "WTPRunState.c",
    "content": "/************************************************************************************************\n * Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica   *\n *                          Universita' Campus BioMedico - Italy                                *\n *                                                                                              *\n * This program is free software; you can redistribute it and/or modify it under the terms      *\n * of the GNU General Public License as published by the Free Software Foundation; either       *\n * version 2 of the License, or (at your option) any later version.                             *\n *                                                                                              *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY              *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                     *\n *                                                                                              *\n * You should have received a copy of the GNU General Public License along with this            *\n * program; if not, write to the:                                                               *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                         *\n * MA  02111-1307, USA.                                                                         *\n *                                                                                              *\n * -------------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                             *\n *                                                                                              *\n * Authors : Ludovico Rossi (ludo@bluepixysw.com)                                               *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                         *\n *           Giovannini Federica (giovannini.federica@gmail.com)                                *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                         *\n *           Mauro Bisson (mauro.bis@gmail.com)                                                 *\n *           Antonio Davoli (antonio.davoli@gmail.com)                                          *\n ************************************************************************************************/\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <linux/if_ether.h>\n#include <net/if.h>\n#include <sys/ioctl.h>\n#include <netpacket/packet.h>\n\n#include \"CWWTP.h\"\n#include \"CWVendorPayloads.h\"\n#include \"WTPipcHostapd.h\"\n#include \"WTPmacFrameReceive.h\"\n#include \"common.h\"\n#include \"ieee802_11_defs.h\"\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nCWBool CWWTPManageGenericRunMessage(CWProtocolMessage * msgPtr);\n\nCWBool CWWTPCheckForBindingFrame();\n\nCWBool CWWTPCheckForWTPEventRequest();\nCWBool CWParseWTPEventResponseMessage(unsigned char *msg, int len, int seqNum, void *values);\n\nCWBool CWSaveWTPEventResponseMessage(void *WTPEventResp);\n\nCWBool CWAssembleEchoRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t     int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList);\n\nCWBool CWParseConfigurationUpdateRequest(unsigned char *msg,\n\t\t\t\t\t int len,\n\t\t\t\t\t CWProtocolConfigurationUpdateRequestValues * valuesPtr,\n\t\t\t\t\t int *updateRequestType);\n\nCWBool CWSaveConfigurationUpdateRequest(CWProtocolConfigurationUpdateRequestValues * valuesPtr,\n\t\t\t\t\tCWProtocolResultCode * resultCode, int *updateRequestType);\n\nCWBool CWAssembleConfigurationUpdateResponse(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t     int *fragmentsNumPtr,\n\t\t\t\t\t     int PMTU,\n\t\t\t\t\t     int seqNum,\n\t\t\t\t\t     CWProtocolResultCode resultCode,\n\t\t\t\t\t     CWProtocolConfigurationUpdateRequestValues values);\n\nCWBool CWSaveClearConfigurationRequest(CWProtocolResultCode * resultCode);\n\nCWBool CWAssembleClearConfigurationResponse(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t    int *fragmentsNumPtr,\n\t\t\t\t\t    int PMTU, int seqNum, CWProtocolResultCode resultCode);\n\nCWBool CWAssembleStationConfigurationResponse(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t      int *fragmentsNumPtr,\n\t\t\t\t\t      int PMTU, int seqNum, CWProtocolResultCode resultCode);\nCWBool CWAssembleWLANConfigurationResponse(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t   int *fragmentsNumPtr, int PMTU, int seqNum, CWProtocolResultCode resultCode);\n\nCWBool CWParseStationConfigurationRequest(unsigned char *msg, int len);\nCWBool CWParseWLANConfigurationRequest(unsigned char *msg, int len);\n\nvoid CWConfirmRunStateToACWithEchoRequest();\nvoid CWWTPKeepAliveDataTimerExpiredHandler(void *arg);\n\nCWTimerID gCWHeartBeatTimerID;\nCWTimerID gCWKeepAliveTimerID;\nCWTimerID gCWNeighborDeadTimerID;\nCWBool gNeighborDeadTimerSet = CW_FALSE;\n\nint gEchoInterval = CW_ECHO_INTERVAL_DEFAULT;\nint gDataChannelKeepAlive = CW_DATA_CHANNEL_KEEP_ALIVE_DEFAULT;\n\n/*\n * Manage DTLS packets.\n */\nCW_THREAD_RETURN_TYPE CWWTPReceiveDtlsPacket(void *arg)\n{\n\n\tint readBytes;\n\tunsigned char buf[CW_BUFFER_SIZE];\n\tCWSocket sockDTLS = (long) arg;\n\tCWNetworkLev4Address addr;\n\tchar *pData;\n\n\tCW_REPEAT_FOREVER {\n\t\tif (!CWErr(CWNetworkReceiveUnsafe(sockDTLS, buf, CW_BUFFER_SIZE - 1, 0, &addr, &readBytes))) {\n\n\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_INTERRUPTED)\n\t\t\t\tcontinue;\n\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Clone data packet */\n\t\tCW_CREATE_OBJECT_SIZE_ERR(pData, readBytes, {\n\t\t\t\t\t  CWLog(\"Out Of Memory\");\n\t\t\t\t\t  return NULL;\n\t\t\t\t\t  }\n\t\t);\n\t\tmemcpy(pData, buf, readBytes);\n\n\t\tCWLockSafeList(gPacketReceiveList);\n\t\tCWAddElementToSafeListTailwitDataFlag(gPacketReceiveList, pData, readBytes, CW_FALSE);\n\t\tCWUnlockSafeList(gPacketReceiveList);\n\t}\n\n\treturn NULL;\n}\n\nextern int gRawSock;\n/*\n * Manage data packets.\n */\n\n#define HLEN_80211  24\nint isEAPOL_Frame(unsigned char *buf, unsigned int len)\n{\n\tunsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n\tint i;\n\n\tfor (i = 0; i < 6; i++)\n\t\tif (rfc1042_header[i] != buf[i + HLEN_80211])\n\t\t\treturn 0;\n\treturn 1;\n}\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveDataPacket(void *arg)\n{\n\tint readBytes;\n\tunsigned char buf[CW_BUFFER_SIZE];\n\tstruct sockaddr_ll rawSockaddr;\n\tCWNetworkLev4Address addr;\n\tCWList fragments = NULL;\n\tCWProtocolMessage msgPtr;\n\tCWBool dataFlag = CW_TRUE;\n\n\tmemset(&rawSockaddr, 0, sizeof(rawSockaddr));\n\n\trawSockaddr.sll_family = AF_PACKET;\n\trawSockaddr.sll_protocol = htons(ETH_P_ALL);\n\trawSockaddr.sll_ifindex = if_nametoindex(gRadioInterfaceName_0);\n\trawSockaddr.sll_pkttype = PACKET_OTHERHOST;\n\trawSockaddr.sll_halen = ETH_ALEN;\n\n\tCW_REPEAT_FOREVER {\n\t\tif (!CWErr(CWNetworkReceiveUnsafe(gWTPDataSocket, buf, CW_BUFFER_SIZE - 1, 0, &addr, &readBytes))) {\n\n\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_INTERRUPTED)\n\t\t\t\tcontinue;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tmsgPtr.msg = NULL;\n\t\tmsgPtr.offset = 0;\n\n\t\tif (!CWProtocolParseFragment(buf, readBytes, &fragments, &msgPtr, &dataFlag, NULL)) {\n\t\t\tif (CWErrorGetLastErrorCode()) {\n\t\t\t\tCWErrorCode error;\n\t\t\t\terror = CWErrorGetLastErrorCode();\n\t\t\t\tswitch (error) {\n\t\t\t\tcase CW_ERROR_SUCCESS:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Success\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_OUT_OF_MEMORY:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Out of Memory\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_WRONG_ARG:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Wrong Argument\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_INTERRUPTED:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Interrupted\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_NEED_RESOURCE:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Need Resource\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_COMUNICATING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Comunicating\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_CREATING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Creating\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_GENERAL:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: General\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_OPERATION_ABORTED:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Operation Aborted\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_SENDING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Sending\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_RECEIVING:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Receiving\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_INVALID_FORMAT:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Invalid Format\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_TIME_EXPIRED:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: Time Expired\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tcase CW_ERROR_NONE:{\n\t\t\t\t\t\tCWDebugLog(\"ERROR: None\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (msgPtr.data_msgType == CW_DATA_MSG_KEEP_ALIVE_TYPE) {\n\n\t\t\t\tunsigned short int elemType = 0;\n\t\t\t\tunsigned short int elemLen = 0;\n\n\t\t\t\tCWDebugLog(\"Got KeepAlive len:%d from AC\", msgPtr.offset);\n\t\t\t\tmsgPtr.offset = 0;\n\t\t\t\tCWParseFormatMsgElem(&msgPtr, &elemType, &elemLen);\n\n\t\t\t} else if (msgPtr.data_msgType == CW_IEEE_802_3_FRAME_TYPE) {\n\n\t\t\t\tCWDebugLog(\"Got 802.3 len:%d from AC\", msgPtr.offset);\n\n\t\t\t\t/*MAC - begin */\n\t\t\t\trawSockaddr.sll_addr[0] = msgPtr.msg[0];\n\t\t\t\trawSockaddr.sll_addr[1] = msgPtr.msg[1];\n\t\t\t\trawSockaddr.sll_addr[2] = msgPtr.msg[2];\n\t\t\t\trawSockaddr.sll_addr[3] = msgPtr.msg[3];\n\t\t\t\trawSockaddr.sll_addr[4] = msgPtr.msg[4];\n\t\t\t\trawSockaddr.sll_addr[5] = msgPtr.msg[5];\n\t\t\t\t/*MAC - end */\n\t\t\t\trawSockaddr.sll_addr[6] = 0x00;\t/*not used */\n\t\t\t\trawSockaddr.sll_addr[7] = 0x00;\t/*not used */\n\n\t\t\t\trawSockaddr.sll_hatype = htons(msgPtr.msg[12] << 8 | msgPtr.msg[13]);\n\n\t\t\t\tsendto(gRawSock, msgPtr.msg, msgPtr.offset, 0, (struct sockaddr *)&rawSockaddr,\n\t\t\t\t\t   sizeof(rawSockaddr));\n\n\t\t\t} else if (msgPtr.data_msgType == CW_IEEE_802_11_FRAME_TYPE) {\n\n\t\t\t\tstruct ieee80211_hdr *hdr;\n\t\t\t\tu16 fc;\n\t\t\t\thdr = (struct ieee80211_hdr *)msgPtr.msg;\n\t\t\t\tfc = le_to_host16(hdr->frame_control);\n\n\t\t\t\tif (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT\n\t\t\t\t    || isEAPOL_Frame(msgPtr.msg, msgPtr.offset)) {\n\t\t\t\t\tCWDebugLog(\"Got 802.11 Management Packet (stype=%d) from AC(hostapd) len:%d\",\n\t\t\t\t\t\t   WLAN_FC_GET_STYPE(fc), msgPtr.offset);\n\t\t\t\t\tCWWTPsend_data_to_hostapd(msgPtr.msg, msgPtr.offset);\n\n\t\t\t\t} else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {\n\n\t\t\t\t\tif (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_NULLFUNC) {\n\n\t\t\t\t\t\tCWDebugLog(\"Got 802.11 Data Packet (stype=%d) from AC(hostapd) len:%d\",\n\t\t\t\t\t\t\t   WLAN_FC_GET_STYPE(fc), msgPtr.offset);\n\t\t\t\t\t\tCWWTPsend_data_to_hostapd(msgPtr.msg, msgPtr.offset);\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tCWDebugLog(\"Got 802.11 Data Packet (stype=%d) from AC(hostapd) len:%d\",\n\t\t\t\t\t\t\t   WLAN_FC_GET_STYPE(fc), msgPtr.offset);\n\t\t\t\t\t\tCWWTPSendFrame(msgPtr.msg, msgPtr.offset);\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tCWLog(\"Control/Unknow Type type=%d\", WLAN_FC_GET_TYPE(fc));\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tCWLog(\"Unknow data_msgType\");\n\t\t\t}\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgPtr);\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\n/*\n * Manage Run State.\n */\n\nextern int gRawSock;\nint wtpInRunState = 0;\nCWStateTransition CWWTPEnterRun()\n{\n\n\tint k;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"######### WTP enters in RUN State #########\");\n\n\tCWWTPKeepAliveDataTimerExpiredHandler(NULL);\n\n\tfor (k = 0; k < MAX_PENDING_REQUEST_MSGS; k++)\n\t\tCWResetPendingMsgBox(gPendingRequestMsgs + k);\n\n\tif (!CWErr(CWStartHeartbeatTimer())) {\n\n\t\treturn CW_ENTER_RESET;\n\t}\n\n\twtpInRunState = 1;\n\n\tCW_REPEAT_FOREVER {\n\n\t\tstruct timespec timenow;\n\t\tCWBool bReceivePacket = CW_FALSE;\n\t\tCWBool bReveiveBinding = CW_FALSE;\n\t\tif (gWTPNextState == CW_ENTER_RESET) {\n        \t\twtpInRunState = 0;\n        \t\tCWStopHeartbeatTimer();\n        \t\treturn CW_ENTER_RESET;\n\t\t}\t\t\n\t\t/* Wait packet */\n\t\tif (gWTPForceACAddress != NULL) \n\t\t\ttimenow.tv_sec = time(0) + CW_NEIGHBORDEAD_INTERVAL_DEFAULT;\n\t\telse\n\t\t\ttimenow.tv_sec = time(0) + CW_NEIGHBORDEAD_RESTART_DISCOVERY_DELTA_DEFAULT;\t/* greater than NeighborDeadInterval */\n\n\t\ttimenow.tv_nsec = 0;\n\n\t\tCWThreadMutexLock(&gInterfaceMutex);\n\n\t\t/*\n\t\t * if there are no frames from stations\n\t\t * and no packets from AC...\n\t\t */\n\t\tif ((CWGetCountElementFromSafeList(gPacketReceiveList) == 0)\n\t\t    && (CWGetCountElementFromSafeList(gFrameList) == 0)) {\n\t\t\t/*\n\t\t\t * ...wait at most 4 mins for a frame or packet.\n\t\t\t */\n\t\t\tif (!CWErr(CWWaitThreadConditionTimeout(&gInterfaceWait, &gInterfaceMutex, &timenow))) {\n\n\t\t\t\tCWThreadMutexUnlock(&gInterfaceMutex);\n\n\t\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_TIME_EXPIRED) {\n\n\t\t\t\t\tCWLog(\"No Message from AC for a long time... restart Discovery State\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tbReceivePacket = ((CWGetCountElementFromSafeList(gPacketReceiveList) != 0) ? CW_TRUE : CW_FALSE);\n\t\tbReveiveBinding = ((CWGetCountElementFromSafeList(gFrameList) != 0) ? CW_TRUE : CW_FALSE);\n\n\t\tCWThreadMutexUnlock(&gInterfaceMutex);\n\n\t\tif (bReceivePacket) {\n\n\t\t\tCWProtocolMessage msg;\n\n\t\t\tmsg.msg = NULL;\n\t\t\tmsg.offset = 0;\n\n\t\t\tif (!(CWReceiveMessage(&msg))) {\n\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t\t\tCWLog(\"Failure Receiving Response\");\n\t\t\t\twtpInRunState = 0;\n\t\t\t\treturn CW_ENTER_RESET;\n\t\t\t}\n\t\t\tif (!CWErr(CWWTPManageGenericRunMessage(&msg))) {\n\n\t\t\t\tif (CWErrorGetLastErrorCode() == CW_ERROR_INVALID_FORMAT) {\n\n\t\t\t\t\t/* Log and ignore message */\n\t\t\t\t\tCWErrorHandleLast();\n\t\t\t\t\tCWLog(\"--> Received something different from a valid Run Message\");\n\t\t\t\t} else {\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(msg);\n\t\t\t\t\tCWLog\n\t\t\t\t\t    (\"--> Critical Error Managing Generic Run Message... we enter RESET State\");\n\t\t\t\t\twtpInRunState = 0;\n\t\t\t\t\treturn CW_ENTER_RESET;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (bReveiveBinding)\n\t\t\tCWWTPCheckForBindingFrame();\n\t}\n\n\twtpInRunState = 0;\n\tCWStopHeartbeatTimer();\n\n\treturn CW_ENTER_RESET;\n}\n\nCWBool CWWTPManageGenericRunMessage(CWProtocolMessage * msgPtr)\n{\n\n\tCWControlHeaderValues controlVal;\n\n\tif (msgPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tmsgPtr->offset = 0;\n\n\t/* will be handled by the caller */\n\tif (!(CWParseControlHeader(msgPtr, &controlVal)))\n\t\treturn CW_FALSE;\n\n\tint len = controlVal.msgElemsLen - CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\tint pendingMsgIndex = 0;\n\tpendingMsgIndex = CWFindPendingRequestMsgsBox(gPendingRequestMsgs,\n\t\t\t\t\t\t      MAX_PENDING_REQUEST_MSGS,\n\t\t\t\t\t\t      controlVal.messageTypeValue, controlVal.seqNum);\n\n\t/* we have received a new Request or an Echo Response */\n\tif (pendingMsgIndex < 0) {\n\n\t\tCWProtocolMessage *messages = NULL;\n\t\tint fragmentsNum = 0;\n\t\tCWBool toSend = CW_FALSE;\n\n\t\tswitch (controlVal.messageTypeValue) {\n\n\t\tcase CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_REQUEST:{\n\t\t\t\tCWProtocolResultCode resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\tCWProtocolConfigurationUpdateRequestValues values;\n\t\t\t\tint updateRequestType;\n\n\t\t\t\t/*Update 2009:\n\t\t\t\t   check to see if a time-out on session occur...\n\t\t\t\t   In case it happens it should go back to CW_ENTER_RESET */\n\t\t\t\tif (!CWResetTimers()) {\n\t\t\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\n\t\t\t\tCWLog(\"Configuration Update Request received\");\n\n\t\t\t/************************************************************************************************\n\t\t\t * Update 2009:                                                                                 *\n\t\t\t *              These two function need an additional parameter (Pointer to updateRequestType)  *\n\t\t\t *              for distinguish between all types of message elements.                          *\n\t\t\t ************************************************************************************************/\n\n\t\t\t\tif (!CWParseConfigurationUpdateRequest\n\t\t\t\t    ((msgPtr->msg) + (msgPtr->offset), len, &values, &updateRequestType))\n\t\t\t\t\treturn CW_FALSE;\n\n\t\t\t\tif (!CWSaveConfigurationUpdateRequest(&values, &resultCode, &updateRequestType))\n\t\t\t\t\treturn CW_FALSE;\n\n\t\t\t\t/*\n\t\t\t\t   if ( updateRequestType == BINDING_MSG_ELEMENT_TYPE_OFDM_CONTROL )\n\t\t\t\t   break;\n\t\t\t\t */\n\n\t\t\t\t/*Update 2009:\n\t\t\t\t   Added values (to return stuff with a conf update response) */\n\t\t\t\tif (!CWAssembleConfigurationUpdateResponse(&messages,\n\t\t\t\t\t\t\t\t\t   &fragmentsNum,\n\t\t\t\t\t\t\t\t\t   gWTPPathMTU,\n\t\t\t\t\t\t\t\t\t   controlVal.seqNum, resultCode, values))\n\t\t\t\t\treturn CW_FALSE;\n\n\t\t\t\ttoSend = CW_TRUE;\n\n\t\t\t\t/*\n\t\t\t\t * BUG-ML01- memory leak fix\n\t\t\t\t *\n\t\t\t\t * 16/10/2009 - Donato Capitella\n\t\t\t\t */\n\t\t\t\t/*\n\t\t\t\t   CWProtocolVendorSpecificValues* psValues = values.protocolValues;\n\t\t\t\t   if (psValues->vendorPayloadType == CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI)\n\t\t\t\t   CW_FREE_OBJECT(((CWVendorUciValues *)psValues->payload)->response);\n\t\t\t\t   CW_FREE_OBJECT(psValues->payload);\n\t\t\t\t   CW_FREE_OBJECT(values.protocolValues);\n\t\t\t\t */\n\t\t\t\tbreak;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_REQUEST:{\n\t\t\t\tCWProtocolResultCode resultCode = CW_PROTOCOL_FAILURE;\n\t\t\t\t/*Update 2009:\n\t\t\t\t   check to see if a time-out on session occur...\n\t\t\t\t   In case it happens it should go back to CW_ENTER_RESET */\n\t\t\t\tif (!CWResetTimers()) {\n\t\t\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t\tCWLog(\"Clear Configuration Request received\");\n\t\t\t\t/*WTP RESET ITS CONFIGURAION TO MANUFACTURING DEFAULT} */\n\t\t\t\tif (!CWSaveClearConfigurationRequest(&resultCode))\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\tif (!CWAssembleClearConfigurationResponse\n\t\t\t\t    (&messages, &fragmentsNum, gWTPPathMTU, controlVal.seqNum, resultCode))\n\t\t\t\t\treturn CW_FALSE;\n\n\t\t\t\ttoSend = CW_TRUE;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_REQUEST:{\n\n\t\t\t\tCWProtocolResultCode resultCode = CW_PROTOCOL_SUCCESS;\n\t\t\t\t//CWProtocolStationConfigurationRequestValues values;  --> da implementare\n\t\t\t\t/*Update 2009:\n\t\t\t\t   check to see if a time-out on session occur...\n\t\t\t\t   In case it happens it should go back to CW_ENTER_RESET */\n\t\t\t\tif (!CWResetTimers()) {\n\t\t\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t\tCWLog(\"Station Configuration Request received\");\n\n\t\t\t\tif (!CWParseStationConfigurationRequest((msgPtr->msg) + (msgPtr->offset), len))\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\tif (!CWAssembleStationConfigurationResponse\n\t\t\t\t    (&messages, &fragmentsNum, gWTPPathMTU, controlVal.seqNum, resultCode))\n\t\t\t\t\treturn CW_FALSE;\n\n\t\t\t\ttoSend = CW_TRUE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase CW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_REQUEST:{\n\n\t\t\t\tCWProtocolResultCode resultCode = CW_PROTOCOL_SUCCESS;\n\n\t\t\t\tif (!CWResetTimers()) {\n\t\t\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t\tCWLog(\"WLAN Configuration Request received\");\n\n\t\t\t\tif (!CWParseWLANConfigurationRequest((msgPtr->msg) + (msgPtr->offset), len))\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\tif (!CWAssembleWLANConfigurationResponse\n\t\t\t\t    (&messages, &fragmentsNum, gWTPPathMTU, controlVal.seqNum, resultCode))\n\t\t\t\t\treturn CW_FALSE;\n\n\t\t\t\ttoSend = CW_TRUE;\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\tcase CW_MSG_TYPE_VALUE_ECHO_RESPONSE:{\n\t\t\t\t/*Update 2009:\n\t\t\t\t   check to see if a time-out on session occur...\n\t\t\t\t   In case it happens it should go back to CW_ENTER_RESET */\n\t\t\t\tif (!CWResetTimers()) {\n\t\t\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t\tCWLog(\"Echo Response received\");\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\t/*\n\t\t\t * We can't recognize the received Request so\n\t\t\t * we have to send a corresponding response\n\t\t\t * containing a failure result code\n\t\t\t */\n\t\t\tCWLog(\"--> Not valid Request in Run State... we send a failure Response\");\n\t\t\t/*Update 2009:\n\t\t\t   check to see if a time-out on session occur...\n\t\t\t   In case it happens it should go back to CW_ENTER_RESET */\n\t\t\tif (!CWResetTimers()) {\n\t\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t\tif (!(CWAssembleUnrecognizedMessageResponse(&messages,\n\t\t\t\t\t\t\t\t    &fragmentsNum,\n\t\t\t\t\t\t\t\t    gWTPPathMTU,\n\t\t\t\t\t\t\t\t    controlVal.seqNum,\n\t\t\t\t\t\t\t\t    controlVal.messageTypeValue + 1)))\n\t\t\t\treturn CW_FALSE;\n\n\t\t\ttoSend = CW_TRUE;\n\t\t\t/* return CWErrorRaise(CW_ERROR_INVALID_FORMAT,\n\t\t\t *             \"Received Message not valid in Run State\");\n\t\t\t */\n\t\t}\n\t\tif (toSend) {\n\n\t\t\tint i;\n\t\t\tfor (i = 0; i < fragmentsNum; i++) {\n#ifdef CW_NO_DTLS\n\t\t\t\tif (!CWNetworkSendUnsafeConnected(gWTPSocket, messages[i].msg, messages[i].offset))\n#else\n\t\t\t\tif (!CWSecuritySend(gWTPSession, messages[i].msg, messages[i].offset))\n#endif\n\t\t\t\t{\n\t\t\t\t\tCWLog(\"Error sending message\");\n\t\t\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\t\t\tCW_FREE_OBJECT(messages);\n\t\t\t\t\treturn CW_FALSE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tCWLog(\"Message Sent\\n\");\n\t\t\tCWFreeMessageFragments(messages, fragmentsNum);\n\t\t\tCW_FREE_OBJECT(messages);\n\n\t\t\t/*\n\t\t\t * Check if we have to exit due to an update commit request.\n\t\t\t */\n\t\t\tif (WTPExitOnUpdateCommit) {\n\t\t\t\texit(EXIT_SUCCESS);\n\t\t\t}\n\t\t}\n\t} else {\t\t/* we have received a Response */\n\n\t\t/*Update 2009:\n\t\t   check to see if a time-out on session occur...\n\t\t   In case it happens it should go back to CW_ENTER_RESET */\n\t\tif (!CWResetTimers())\n\t\t\treturn CW_FALSE;\n\n\t\tswitch (controlVal.messageTypeValue) {\n\t\tcase CW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_RESPONSE:\n\t\t\tCWLog(\"Change State Event Response received\");\n\t\t\tbreak;\n\n\t\tcase CW_MSG_TYPE_VALUE_WTP_EVENT_RESPONSE:\n\t\t\tCWLog(\"WTP Event Response received\");\n\t\t\tbreak;\n\n\t\tcase CW_MSG_TYPE_VALUE_DATA_TRANSFER_RESPONSE:\n\t\t\tCWLog(\"Data Transfer Response received\");\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/*\n\t\t\t * We can't recognize the received Response: we\n\t\t\t * ignore the message and log the event.\n\t\t\t */\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Received Message not valid in Run State\");\n\t\t}\n\t\tCWResetPendingMsgBox(&(gPendingRequestMsgs[pendingMsgIndex]));\n\t}\n\tCW_FREE_PROTOCOL_MESSAGE(*msgPtr);\n\treturn CW_TRUE;\n}\n\n/*______________________________________________________________*/\n/*  *******************___TIMER HANDLERS___*******************  */\nvoid CWWTPHeartBeatTimerExpiredHandler(void *arg)\n{\n\n\tCWList msgElemList = NULL;\n\tCWProtocolMessage *messages = NULL;\n\tint fragmentsNum = 0;\n\tint seqNum;\n\n\tif (!gNeighborDeadTimerSet) {\n\n\t\tif (!CWStartNeighborDeadTimer()) {\n\t\t\tCWStopHeartbeatTimer();\n\t\t\tCWStopNeighborDeadTimer();\n\t\t\treturn;\n\t\t}\n\t}\n\n\tCWLog(\"WTP HeartBeat Timer Expired... we send an ECHO Request\");\n\n\tCWLog(\"\\n\");\n\tCWLog(\"#________ Echo Request Message (Run) ________#\");\n\n\t/* Send WTP Event Request */\n\tseqNum = CWGetSeqNum();\n\n\tif (!CWAssembleEchoRequest(&messages, &fragmentsNum, gWTPPathMTU, seqNum, msgElemList)) {\n\t\tint i;\n\n\t\tCWDebugLog(\"Failure Assembling Echo Request\");\n\t\tif (messages)\n\t\t\tfor (i = 0; i < fragmentsNum; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t\t\t}\n\t\tCW_FREE_OBJECT(messages);\n\t\treturn;\n\t}\n\n\tint i;\n\tfor (i = 0; i < fragmentsNum; i++) {\n#ifdef CW_NO_DTLS\n\t\tif (!CWNetworkSendUnsafeConnected(gWTPSocket, messages[i].msg, messages[i].offset)) {\n#else\n\t\tif (!CWSecuritySend(gWTPSession, messages[i].msg, messages[i].offset)) {\n#endif\n\t\t\tCWLog(\"Failure sending Request\");\n\t\t\tint k;\n\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(messages);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tint k;\n\tfor (k = 0; messages && k < fragmentsNum; k++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t}\n\tCW_FREE_OBJECT(messages);\n\n\tif (!CWStartHeartbeatTimer()) {\n\t\treturn;\n\t}\n}\n\nvoid CWWTPKeepAliveDataTimerExpiredHandler(void *arg)\n{\n\n\tCWProtocolMessage *messages = NULL;\n\tCWProtocolMessage sessionIDmsgElem;\n\tint fragmentsNum = 0;\n\n\tCWAssembleMsgElemSessionID(&sessionIDmsgElem, &gWTPSessionID[0]);\n\n\t/* Send WTP Event Request */\n\tif (!CWAssembleDataMessage(&messages, &fragmentsNum, gWTPPathMTU, &sessionIDmsgElem, NULL, CW_PACKET_PLAIN, 1)) {\n\t\tint i;\n\n\t\tCWDebugLog(\"Failure Assembling KeepAlive Request\");\n\t\tif (messages)\n\t\t\tfor (i = 0; i < fragmentsNum; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t\t\t}\n\t\tCW_FREE_OBJECT(messages);\n\t\treturn;\n\t}\n\n\tint i;\n\tfor (i = 0; i < fragmentsNum; i++) {\n\n\t\tif (!CWNetworkSendUnsafeConnected(gWTPDataSocket, messages[i].msg, messages[i].offset)) {\n\t\t\tCWLog(\"Failure sending  KeepAlive Request\");\n\t\t\tint k;\n\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(messages);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tint k;\n\tfor (k = 0; messages && k < fragmentsNum; k++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t}\n\tCW_FREE_OBJECT(messages);\n}\n\nvoid CWWTPNeighborDeadTimerExpired(void *arg)\n{\n\n\tCWLog(\"WTP NeighborDead Timer Expired... we consider Peer Dead.\");\n\n#ifdef DMALLOC\n\tdmalloc_shutdown();\n#endif\n\n\treturn;\n}\n\nCWBool CWStartHeartbeatTimer()\n{\n\n\tgCWHeartBeatTimerID = timer_add(gEchoInterval, 0, &CWWTPHeartBeatTimerExpiredHandler, NULL);\n\n\tif (gCWHeartBeatTimerID == -1)\n\t\treturn CW_FALSE;\n\n\tCWDebugLog(\"Echo Heartbeat Timer Started\");\n\tgCWKeepAliveTimerID = timer_add(gDataChannelKeepAlive, 0, &CWWTPKeepAliveDataTimerExpiredHandler, NULL);\n\n\tif (gCWKeepAliveTimerID == -1)\n\t\treturn CW_FALSE;\n\n\tCWDebugLog(\"Keepalive Heartbeat Timer Started\");\n\treturn CW_TRUE;\n}\n\nCWBool CWStopHeartbeatTimer()\n{\n\n\ttimer_rem(gCWHeartBeatTimerID, NULL);\n\tCWDebugLog(\"Echo Heartbeat Timer Stopped\");\n\ttimer_rem(gCWKeepAliveTimerID, NULL);\n\tCWDebugLog(\"KeepAlive Heartbeat Timer Stopped\");\n\treturn CW_TRUE;\n}\n\nCWBool CWStartNeighborDeadTimer()\n{\n\n\tgCWNeighborDeadTimerID = timer_add(gCWNeighborDeadInterval, 0, &CWWTPNeighborDeadTimerExpired, NULL);\n\n\tif (gCWNeighborDeadTimerID == -1)\n\t\treturn CW_FALSE;\n\n\tCWDebugLog(\"NeighborDead Timer Started\");\n\tgNeighborDeadTimerSet = CW_TRUE;\n\treturn CW_TRUE;\n}\n\nCWBool CWStopNeighborDeadTimer()\n{\n\n\ttimer_rem(gCWNeighborDeadTimerID, NULL);\n\tCWDebugLog(\"NeighborDead Timer Stopped\");\n\tgNeighborDeadTimerSet = CW_FALSE;\n\treturn CW_TRUE;\n}\n\nCWBool CWResetTimers()\n{\n\n\tif (gNeighborDeadTimerSet) {\n\n\t\tif (!CWStopNeighborDeadTimer())\n\t\t\treturn CW_FALSE;\n\t}\n\n\tif (!CWStopHeartbeatTimer())\n\t\treturn CW_FALSE;\n\n\tif (!CWStartHeartbeatTimer())\n\t\treturn CW_FALSE;\n\n\treturn CW_TRUE;\n}\n\n/*__________________________________________________________________*/\n/*  *******************___ASSEMBLE FUNCTIONS___*******************  */\nCWBool CWAssembleEchoRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t     int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 0;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Echo Request...\");\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_ECHO_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"Echo Request Assembled\");\n\n\treturn CW_TRUE;\n}\n\n\nCWBool CWAssembleWTPDataTransferRequest(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum,\n\t\t\t\t\tCWList msgElemList)\n{\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 0;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\tint i;\n\tCWListElement *current;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL || msgElemList == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tmsgElemCount = CWCountElementInList(msgElemList);\n\n\tif (msgElemCount > 0) {\n\t\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount,\n\t\t\t\t\t\t return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t} else\n\t\tmsgElems = NULL;\n\n\tCWLog(\"Assembling WTP Data Transfer Request...\");\n\n\tcurrent = msgElemList;\n\tfor (i = 0; i < msgElemCount; i++) {\n\t\tswitch (((CWMsgElemData *) current->data)->type) {\n\t\tcase CW_MSG_ELEMENT_DATA_TRANSFER_DATA_CW_TYPE:\n\t\t\tif (!\n\t\t\t    (CWAssembleMsgElemDataTransferData\n\t\t\t     (&(msgElems[++k]), ((CWMsgElemData *) current->data)->value)))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\t\t/*case CW_MSG_ELEMENT_DATA_TRANSFER_MODE_CW_TYPE:\n\t\t\t   if (!(CWAssembleMsgElemDataTansferMode(&(msgElems[++k]))))\n\t\t\t   goto cw_assemble_error;\n\t\t\t   break; */\n\n\t\tdefault:\n\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\t}\n\n\t\tcurrent = current->next;\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_DATA_TRANSFER_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"WTP Data Transfer Request Assembled\");\n\n\treturn CW_TRUE;\n\n cw_assemble_error:{\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t}\n}\n\nCWBool CWAssembleWTPEventRequest(CWProtocolMessage ** messagesPtr,\n\t\t\t\t int *fragmentsNumPtr, int PMTU, int seqNum, CWList msgElemList)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tint msgElemCount = 0;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\tint i;\n\tCWListElement *current;\n\tint k = -1;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL || msgElemList == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tmsgElemCount = CWCountElementInList(msgElemList);\n\n\tif (msgElemCount > 0) {\n\n\t\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems,\n\t\t\t\t\t\t msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t} else\n\t\tmsgElems = NULL;\n\n\tCWLog(\"Assembling WTP Event Request...\");\n\n\tcurrent = msgElemList;\n\tfor (i = 0; i < msgElemCount; i++) {\n\n\t\tswitch (((CWMsgElemData *) current->data)->type) {\n\n\t\tcase CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_CW_TYPE:\n\t\t\tif (!\n\t\t\t    (CWAssembleMsgElemDecryptErrorReport\n\t\t\t     (&(msgElems[++k]), ((CWMsgElemData *) current->data)->value)))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_DUPLICATE_IPV4_ADDRESS_CW_TYPE:\n\t\t\tif (!(CWAssembleMsgElemDuplicateIPv4Address(&(msgElems[++k]))))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_DUPLICATE_IPV6_ADDRESS_CW_TYPE:\n\t\t\tif (!(CWAssembleMsgElemDuplicateIPv6Address(&(msgElems[++k]))))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_OPERAT_STATISTICS_CW_TYPE:\n\t\t\tif (!\n\t\t\t    (CWAssembleMsgElemWTPOperationalStatistics\n\t\t\t     (&(msgElems[++k]), ((CWMsgElemData *) current->data)->value)))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_RADIO_STATISTICS_CW_TYPE:\n\t\t\tif (!\n\t\t\t    (CWAssembleMsgElemWTPRadioStatistics\n\t\t\t     (&(msgElems[++k]), ((CWMsgElemData *) current->data)->value)))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_WTP_REBOOT_STATISTICS_CW_TYPE:\n\t\t\tif (!(CWAssembleMsgElemWTPRebootStatistics(&(msgElems[++k]))))\n\t\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tgoto cw_assemble_error;\n\t\t\tbreak;\n\t\t}\n\t\tcurrent = current->next;\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_WTP_EVENT_REQUEST,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"WTP Event Request Assembled\");\n\n\treturn CW_TRUE;\n\n cw_assemble_error:{\n\t\tint i;\n\t\tfor (i = 0; i <= k; i++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(msgElems[i]);\n\t\t}\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\t// error will be handled by the caller\n\t}\n}\n\n/*Update 2009:\n    Added values to args... values is used to determine if we have some\n    payload (in this case only vendor and only UCI) to send back with the\n    configuration update response*/\nCWBool CWAssembleConfigurationUpdateResponse(CWProtocolMessage ** messagesPtr,\n\t\t\t\t\t     int *fragmentsNumPtr,\n\t\t\t\t\t     int PMTU,\n\t\t\t\t\t     int seqNum,\n\t\t\t\t\t     CWProtocolResultCode resultCode,\n\t\t\t\t\t     CWProtocolConfigurationUpdateRequestValues values)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 1;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\tCWProtocolVendorSpecificValues *protoValues = NULL;\n\n\t/*Get protocol data if we have it */\n\tif (values.protocolValues)\n\t\tprotoValues = (CWProtocolVendorSpecificValues *) values.protocolValues;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Configuration Update Response...\");\n\n\tCW_CREATE_OBJECT_ERR(msgElems, CWProtocolMessage, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (protoValues) {\n\t\tswitch (protoValues->vendorPayloadType) {\n\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\t\tif (!(CWAssembleVendorMsgElemResultCodeWithPayload(msgElems, resultCode, protoValues))) {\n\t\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/*Result Code only */\n\t\t\tif (!(CWAssembleMsgElemResultCode(msgElems, resultCode))) {\n\t\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\t\treturn CW_FALSE;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/*Result Code only */\n\t\tif (!(CWAssembleMsgElemResultCode(msgElems, resultCode))) {\n\t\t\tCW_FREE_OBJECT(msgElems);\n\t\t\treturn CW_FALSE;\n\t\t}\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"Configuration Update Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleClearConfigurationResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU,\n\t\t\t\t\t    int seqNum, CWProtocolResultCode resultCode)\n{\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 1;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Clear Configuration Response...\");\n\n\tCW_CREATE_OBJECT_ERR(msgElems, CWProtocolMessage, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!(CWAssembleMsgElemResultCode(msgElems, resultCode))) {\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"Clear Configuration Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleStationConfigurationResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU,\n\t\t\t\t\t      int seqNum, CWProtocolResultCode resultCode)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 1;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling Sattion Configuration Response...\");\n\n\tCW_CREATE_OBJECT_ERR(msgElems, CWProtocolMessage, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!(CWAssembleMsgElemResultCode(msgElems, resultCode))) {\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"Station Configuration Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWAssembleWLANConfigurationResponse(CWProtocolMessage ** messagesPtr, int *fragmentsNumPtr, int PMTU, int seqNum,\n\t\t\t\t\t   CWProtocolResultCode resultCode)\n{\n\n\tCWProtocolMessage *msgElems = NULL;\n\tconst int msgElemCount = 1;\n\tCWProtocolMessage *msgElemsBinding = NULL;\n\tconst int msgElemBindingCount = 0;\n\tint k = -1;\n\tif (messagesPtr == NULL || fragmentsNumPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Assembling WLAN Configuration Response...\");\n\n\t//CW_CREATE_OBJECT_ERR(msgElems, CWProtocolMessage, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););\n\tCW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tif (!(CWAssembleMsgElemResultCode((&(msgElems[++k])), resultCode))) {\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\n\t}\n\t/*\n\tif (!(CWAssembleMsgElemVendorSpecificPayload((&(msgElems[++k]))))) {\n\t\tCW_FREE_OBJECT(msgElems);\n\t\treturn CW_FALSE;\n\t}\n\t*/\n\n\tif (!(CWAssembleMessage(messagesPtr,\n\t\t\t\tfragmentsNumPtr,\n\t\t\t\tPMTU,\n\t\t\t\tseqNum,\n\t\t\t\tCW_MSG_TYPE_VALUE_WLAN_CONFIGURATION_RESPONSE,\n\t\t\t\tmsgElems, msgElemCount, msgElemsBinding, msgElemBindingCount)))\n\t\treturn CW_FALSE;\n\n\tCWLog(\"WLAN Configuration Response Assembled\");\n\n\treturn CW_TRUE;\n}\n\n/*_______________________________________________________________*/\n/*  *******************___PARSE FUNCTIONS___*******************  */\n/*Update 2009:\n    Function that parses vendor payload,\n    filling in valuesPtr*/\nCWBool CWParseVendorMessage(unsigned char *msg, int len, void **valuesPtr)\n{\n\tCWProtocolMessage completeMsg;\n\tunsigned short int GlobalElemType = 0;\t// = CWProtocolRetrieve32(&completeMsg);\n\n\tif (msg == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing Vendor Specific Message...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tCWProtocolVendorSpecificValues *vendPtr;\n\n\t// parse message elements\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int elemType = 0;\t// = CWProtocolRetrieve32(&completeMsg);\n\t\tunsigned short int elemLen = 0;\t// = CWProtocolRetrieve16(&completeMsg);\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\tGlobalElemType = elemType;\n\n\t\t//CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen);\n\n\t\tswitch (elemType) {\n\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE:\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (elemType == CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE) {\n\t\t\t\tCW_FREE_OBJECT(valuesPtr);\n\t\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t\t} else {\n\t\t\t\tcompleteMsg.offset += elemLen;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tswitch (GlobalElemType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE:\n\t\tCW_CREATE_OBJECT_ERR(vendPtr, CWProtocolVendorSpecificValues,\n\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t    );\n\t\t/*Allocate various other vendor specific fields */\n\t\tbreak;\n\tdefault:\n\t\tvendPtr = NULL;\n\t\tbreak;\n\t}\n\n\tcompleteMsg.offset = 0;\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int type = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(&completeMsg, &type, &elemLen);\n\n\t\tswitch (type) {\n\t\t\t/*Once we know it is a vendor specific payload... */\n\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE:{\n\t\t\t\tif (!\n\t\t\t\t    (CWParseVendorPayload\n\t\t\t\t     (&completeMsg, elemLen, (CWProtocolVendorSpecificValues *) vendPtr))) {\n\t\t\t\t\tCW_FREE_OBJECT(vendPtr);\n\t\t\t\t\treturn CW_FALSE;\t// will be handled by the caller\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t*valuesPtr = (void *)vendPtr;\n\tCWLog(\"Vendor Message Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseConfigurationUpdateRequest(unsigned char *msg,\n\t\t\t\t\t int len,\n\t\t\t\t\t CWProtocolConfigurationUpdateRequestValues * valuesPtr, int *updateRequestType)\n{\n\n\tCWBool bindingMsgElemFound = CW_FALSE;\n\tCWBool vendorMsgElemFound = CW_FALSE;\n\tCWProtocolMessage completeMsg;\n\tunsigned short int GlobalElementType = 0;\n\n\tif (msg == NULL || valuesPtr == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing Configuration Update Request...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\tvaluesPtr->bindingValues = NULL;\n\t/*Update 2009:\n\t   added protocolValues (non-binding) */\n\tvaluesPtr->protocolValues = NULL;\n\n\t/* parse message elements */\n\twhile (completeMsg.offset < len) {\n\n\t\tunsigned short int elemType = 0;\t/* = CWProtocolRetrieve32(&completeMsg); */\n\t\tunsigned short int elemLen = 0;\t/* = CWProtocolRetrieve16(&completeMsg); */\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\tGlobalElementType = elemType;\n\n\t\t/* CWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen); */\n\t\tCWLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen);\n\n\t\tif (CWBindingCheckType(elemType)) {\n\n\t\t\tbindingMsgElemFound = CW_TRUE;\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tcontinue;\n\t\t}\n\t\tswitch (elemType) {\n\t\t\t/*Update 2009:\n\t\t\t   Added case for vendor specific payload\n\t\t\t   (Used mainly to parse UCI messages)... */\n\t\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE:\n\t\t\tvendorMsgElemFound = CW_TRUE;\n\t\t\tcompleteMsg.offset += elemLen;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\t/*Update 2009:\n\t   deal with vendor specific messages */\n\tif (vendorMsgElemFound) {\n\t\t/* For the knownledge of SaveConfiguration */\n\t\t*updateRequestType = GlobalElementType;\n\n\t\tif (!(CWParseVendorMessage(msg, len, &(valuesPtr->protocolValues)))) {\n\n\t\t\treturn CW_FALSE;\n\t\t}\n\t}\n\n\tif (bindingMsgElemFound) {\n\t\t/* For the knownledge of SaveConfiguration */\n\t\t*updateRequestType = GlobalElementType;\n\n\t\tif (!(CWBindingParseConfigurationUpdateRequest(msg, len, &(valuesPtr->bindingValues)))) {\n\n\t\t\treturn CW_FALSE;\n\t\t}\n\t}\n\n\tCWLog(\"Configure Update Request Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseWLANConfigurationRequest(unsigned char *msg, int len)\n{\n\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing WLAN Configuration Request...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\t// parse message elements\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\tswitch (elemType) {\n\n\t\tcase CW_MSG_ELEMENT_IEEE80211_ADD_WLAN_CW_TYPE:\n\n\t\t\tif (!(CWParseAddWLAN(&completeMsg, elemLen)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tcase CW_MSG_ELEMENT_IEEE80211_DELETE_WLAN_CW_TYPE:\n\n\t\t\tif (!(CWParseDeleteWLAN(&completeMsg, elemLen)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\n\tCWLog(\"Station WLAN Request Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseStationConfigurationRequest(unsigned char *msg, int len)\n{\n\t//CWBool bindingMsgElemFound=CW_FALSE;\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing Station Configuration Request...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\t//valuesPtr->bindingValues = NULL;\n\n\t// parse message elements\n\twhile (completeMsg.offset < len) {\n\t\tunsigned short int elemType = 0;\n\t\tunsigned short int elemLen = 0;\n\n\t\tCWParseFormatMsgElem(&completeMsg, &elemType, &elemLen);\n\n\t\tCWDebugLog(\"Parsing Message Element: %u, elemLen: %u\", elemType, elemLen);\n\n\t\t/*if(CWBindingCheckType(elemType))\n\t\t   {\n\t\t   bindingMsgElemFound=CW_TRUE;\n\t\t   completeMsg.offset += elemLen;\n\t\t   continue;\n\t\t   } */\n\n\t\tswitch (elemType) {\n\n\t\tcase CW_MSG_ELEMENT_ADD_STATION_CW_TYPE:\n\n\t\t\tif (!(CWParseAddStation(&completeMsg, elemLen)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tcase CW_MSG_ELEMENT_DELETE_STATION_CW_TYPE:\n\n\t\t\tif (!(CWParseDeleteStation(&completeMsg, elemLen)))\n\t\t\t\treturn CW_FALSE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Unrecognized Message Element\");\n\t\t}\n\t}\n\n\tif (completeMsg.offset != len)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Garbage at the End of the Message\");\n\t/*\n\t   if(bindingMsgElemFound)\n\t   {\n\t   if(!(CWBindingParseConfigurationUpdateRequest (msg, len, &(valuesPtr->bindingValues))))\n\t   {\n\t   return CW_FALSE;\n\t   }\n\t   } */\n\n\tCWLog(\"Station Configuration Request Parsed\");\n\n\treturn CW_TRUE;\n}\n\nCWBool CWParseWTPEventResponseMessage(unsigned char *msg, int len, int seqNum, void *values)\n{\n\n\tCWControlHeaderValues controlVal;\n\tCWProtocolMessage completeMsg;\n\n\tif (msg == NULL)\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n\tCWLog(\"Parsing WTP Event Response...\");\n\n\tcompleteMsg.msg = msg;\n\tcompleteMsg.offset = 0;\n\n\t/* error will be handled by the caller */\n\tif (!(CWParseControlHeader(&completeMsg, &controlVal)))\n\t\treturn CW_FALSE;\n\n\t/* different type */\n\tif (controlVal.messageTypeValue != CW_MSG_TYPE_VALUE_WTP_EVENT_RESPONSE)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not WTP Event Response as Expected\");\n\n\tif (controlVal.seqNum != seqNum)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Different Sequence Number\");\n\n\t/* skip timestamp */\n\tcontrolVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;\n\n\tif (controlVal.msgElemsLen != 0)\n\t\treturn CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"WTP Event Response must carry no message element\");\n\n\tCWLog(\"WTP Event Response Parsed...\");\n\n\treturn CW_TRUE;\n}\n\n/*______________________________________________________________*/\n/*  *******************___SAVE FUNCTIONS___*******************  */\nCWBool CWSaveWTPEventResponseMessage(void *WTPEventResp)\n{\n\n\tCWDebugLog(\"Saving WTP Event Response...\");\n\tCWDebugLog(\"WTP Response Saved\");\n\treturn CW_TRUE;\n}\n\n/*Update 2009:\n    Save a vendor message (mainly UCI configuration messages)*/\nCWBool CWSaveVendorMessage(void *protocolValuesPtr, CWProtocolResultCode * resultCode)\n{\n\tif (protocolValuesPtr == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\t*resultCode = CW_PROTOCOL_SUCCESS;\n\n\tCWProtocolVendorSpecificValues *vendorPtr = (CWProtocolVendorSpecificValues *) protocolValuesPtr;\n\n\t/*Find out which custom vendor paylod really is... */\n\tswitch (vendorPtr->vendorPayloadType) {\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:\n\t\tif (!CWWTPSaveUCIValues((CWVendorUciValues *) (vendorPtr->payload), resultCode)) {\n\t\t\tCW_FREE_OBJECT(((CWVendorUciValues *) vendorPtr->payload)->commandArgs);\n\t\t\tCW_FREE_OBJECT(vendorPtr->payload);\n\t\t\tCW_FREE_OBJECT(vendorPtr);\n\t\t\treturn CW_FALSE;\n\t\t}\n\t\tbreak;\n\n\tcase CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:\n\t\tif (!CWWTPSaveWUMValues((CWVendorWumValues *) (vendorPtr->payload), resultCode)) {\n\t\t\tCW_FREE_OBJECT(vendorPtr->payload);\n\t\t\tCW_FREE_OBJECT(vendorPtr);\n\t\t\treturn CW_FALSE;\n\t\t}\n\t\tbreak;\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveConfigurationUpdateRequest(CWProtocolConfigurationUpdateRequestValues * valuesPtr,\n\t\t\t\t\tCWProtocolResultCode * resultCode, int *updateRequestType)\n{\n\n\t*resultCode = CW_TRUE;\n\n\tif (valuesPtr == NULL) {\n\t\treturn CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\t}\n\n\tif (valuesPtr->bindingValues != NULL) {\n\n\t\tif (!CWBindingSaveConfigurationUpdateRequest(valuesPtr->bindingValues, resultCode, updateRequestType))\n\t\t\treturn CW_FALSE;\n\t}\n\tif (valuesPtr->protocolValues != NULL) {\n\t\t/*Update 2009:\n\t\t   We have a msg which is not a\n\t\t   binding specific message... */\n\t\tif (!CWSaveVendorMessage(valuesPtr->protocolValues, resultCode))\n\t\t\treturn CW_FALSE;\n\t}\n\treturn CW_TRUE;\n}\n\nCWBool CWSaveClearConfigurationRequest(CWProtocolResultCode * resultCode)\n{\n\t*resultCode = CW_TRUE;\n\n\t/*Back to manufacturing default configuration */\n\n\tif (!CWErr(CWWTPLoadConfiguration()) || !CWErr(CWWTPInitConfiguration())) {\n\t\tCWLog(\"Can't restore default configuration...\");\n\t\treturn CW_FALSE;\n\t}\n\n\t*resultCode = CW_TRUE;\n\treturn CW_TRUE;\n}\n\n/*\nCWBool CWWTPManageACRunRequest(char *msg, int len)\n{\n    CWControlHeaderValues controlVal;\n    CWProtocolMessage completeMsg;\n\n    if(msg == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);\n\n    completeMsg.msg = msg;\n    completeMsg.offset = 0;\n\n    if(!(CWParseControlHeader(&completeMsg, &controlVal))) return CW_FALSE; // error will be handled by the caller\n\n    switch(controlVal.messageTypeValue) {\n        case CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_REQUEST:\n            break;\n        case CW_MSG_TYPE_VALUE_ECHO_REQUEST:\n            break;\n        case CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_REQUEST:\n            break;\n        case CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_REQUEST:\n            break;\n        default:\n            return CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Message is not Change State Event Response as Expected\");\n    }\n\n    //if(controlVal.seqNum != seqNum) return CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Different Sequence Number\");\n\n    controlVal.msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS; // skip timestamp\n\n    if(controlVal.msgElemsLen != 0 ) return CWErrorRaise(CW_ERROR_INVALID_FORMAT, \"Change State Event Response must carry no message elements\");\n\n    CWDebugLog(\"Change State Event Response Parsed\");\n\n    CWDebugLog(\"#########################\");\n    CWDebugLog(\"###### STO DENTRO #######\");\n    CWDebugLog(\"#########################\");\n\n    return CW_TRUE;\n}\n*/\n\nvoid CWConfirmRunStateToACWithEchoRequest()\n{\n\n\tCWList msgElemList = NULL;\n\tCWProtocolMessage *messages = NULL;\n\tint fragmentsNum = 0;\n\tint seqNum;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"#________ Echo Request Message (Confirm Run) ________#\");\n\n\t/* Send WTP Event Request */\n\tseqNum = CWGetSeqNum();\n\n\tif (!CWAssembleEchoRequest(&messages, &fragmentsNum, gWTPPathMTU, seqNum, msgElemList)) {\n\t\tint i;\n\n\t\tCWDebugLog(\"Failure Assembling Echo Request\");\n\t\tif (messages)\n\t\t\tfor (i = 0; i < fragmentsNum; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t\t\t}\n\t\tCW_FREE_OBJECT(messages);\n\t\treturn;\n\t}\n\n\tint i;\n\tfor (i = 0; i < fragmentsNum; i++) {\n#ifdef CW_NO_DTLS\n\t\tif (!CWNetworkSendUnsafeConnected(gWTPSocket, messages[i].msg, messages[i].offset)) {\n#else\n\t\tif (!CWSecuritySend(gWTPSession, messages[i].msg, messages[i].offset)) {\n#endif\n\t\t\tCWLog(\"Failure sending Request\");\n\t\t\tint k;\n\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(messages);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tint k;\n\tfor (k = 0; messages && k < fragmentsNum; k++) {\n\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t}\n\tCW_FREE_OBJECT(messages);\n\n}\n"
  },
  {
    "path": "WTPRunStateCheck.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n/*_______________________________________________________________*/\n/*  *******************___CHECK FUNCTIONS___*******************  */\n\nCWBool CWWTPCheckForBindingFrame()\n{\n\t//\n\tCWLockSafeList(gFrameList);\n\n\twhile (CWGetCountElementFromSafeList(gFrameList) > 0) {\n\t\tCWBindingDataListElement *dataFirstElem = CWRemoveHeadElementFromSafeList(gFrameList, NULL);\n\t\tif (dataFirstElem) {\n\t\t\tint k;\n\t\t\tint fragmentsNum = 0;\n\t\t\tCWProtocolMessage *completeMsgPtr = NULL;\n\n\t\t\tif (!CWAssembleDataMessage(&completeMsgPtr,\n\t\t\t\t\t\t   &fragmentsNum,\n\t\t\t\t\t\t   gWTPPathMTU,\n\t\t\t\t\t\t   dataFirstElem->frame,\n\t\t\t\t\t\t   dataFirstElem->bindingValues, CW_PACKET_PLAIN, 0)) {\n\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t\t}\n\n\t\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(*(dataFirstElem->frame));\n\t\t\t\tCW_FREE_OBJECT(dataFirstElem->frame);\n\t\t\t\tCW_FREE_OBJECT(dataFirstElem->bindingValues);\n\t\t\t\tCW_FREE_OBJECT(dataFirstElem);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\tif (!CWNetworkSendUnsafeConnected\n\t\t\t\t    (gWTPDataSocket, completeMsgPtr[k].msg, completeMsgPtr[k].offset)) {\n\t\t\t\t\tCWDebugLog(\"Failure sending Request\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tCWDebugLog(\"Sending binding Request to AC\");\n\t\t\t}\n\n\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t}\n\n\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(*(dataFirstElem->frame));\n\t\t\tCW_FREE_OBJECT(dataFirstElem->frame);\n\t\t\tCW_FREE_OBJECT(dataFirstElem->bindingValues);\n\t\t\tCW_FREE_OBJECT(dataFirstElem);\n\t\t}\n\t}\n\n\tCWUnlockSafeList(gFrameList);\n\n\treturn CW_TRUE;\n}\n\nCWBool CWWTPCheckForWTPEventRequest()\n{\n\n\tCWLog(\"\\n\");\n\tCWLog(\"#________ WTP Event Request Message (Run) ________#\");\n\n\t/* Send WTP Event Request */\n\tCWList msgElemList = NULL;\n\tCWProtocolMessage *messages = NULL;\n\tint fragmentsNum = 0;\n\tint seqNum;\n\tint *pendingReqIndex;\n\n\tseqNum = CWGetSeqNum();\n\n\tCW_CREATE_OBJECT_ERR(pendingReqIndex, int, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\n\tCW_CREATE_OBJECT_ERR(msgElemList, CWListElement, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tCW_CREATE_OBJECT_ERR(msgElemList->data, CWMsgElemData, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t    );\n\tmsgElemList->next = NULL;\n\t//Change type and value to change the msg elem to send\n\t((CWMsgElemData *) (msgElemList->data))->type = CW_MSG_ELEMENT_CW_DECRYPT_ER_REPORT_CW_TYPE;\n\t((CWMsgElemData *) (msgElemList->data))->value = 0;\n\n\tif (!CWAssembleWTPEventRequest(&messages, &fragmentsNum, gWTPPathMTU, seqNum, msgElemList)) {\n\t\tint i;\n\t\tif (messages)\n\t\t\tfor (i = 0; i < fragmentsNum; i++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[i]);\n\t\t\t}\n\t\tCW_FREE_OBJECT(messages);\n\t\treturn CW_FALSE;\n\t}\n\n\t*pendingReqIndex = CWSendPendingRequestMessage(gPendingRequestMsgs, messages, fragmentsNum);\n\tif (*pendingReqIndex < 0) {\n\t\tCWDebugLog(\"Failure sending WTP Event Request\");\n\t\tint k;\n\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\tCW_FREE_PROTOCOL_MESSAGE(messages[k]);\n\t\t}\n\t\tCW_FREE_OBJECT(messages);\n\t\tCWDeleteList(&msgElemList, CWProtocolDestroyMsgElemData);\n\t\treturn CW_FALSE;\n\t}\n\tCWUpdatePendingMsgBox(&(gPendingRequestMsgs[*pendingReqIndex]),\n\t\t\t      CW_MSG_TYPE_VALUE_WTP_EVENT_RESPONSE,\n\t\t\t      seqNum,\n\t\t\t      gCWRetransmitTimer,\n\t\t\t      pendingReqIndex, CWWTPRetransmitTimerExpiredHandler, 0, messages, fragmentsNum);\n\n\tCWDeleteList(&msgElemList, CWProtocolDestroyMsgElemData);\n\n\treturn CW_TRUE;\n}\n\n/*\nvoid CWWTPRetransmitTimerExpiredHandler(CWTimerArg arg, CWTimerID id)\n{\n    CWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n    CWDebugLog(\"Retransmit Timer Expired for Thread: %08x\", (unsigned int)CWThreadSelf());\n\n    if(gPendingRequestMsgs[arg].retransmission == gCWMaxRetransmit) {\n        CWDebugLog(\"Peer is Dead\");\n        CWThreadSetSignals(SIG_UNBLOCK, 1, SIGALRM);\n        //_CWCloseThread(*iPtr);\n        return;\n    }\n\n    CWDebugLog(\"Retransmission Count increases to %d\", gPendingRequestMsgs[arg].retransmission);\n\n    int i;\n    for(i = 0; i < gPendingRequestMsgs[arg].fragmentsNum; i++) {\n        if(!CWSecuritySend(gWTPSession, gPendingRequestMsgs[arg].msgElems[i].msg, gPendingRequestMsgs[arg].msgElems[i].offset)){\n            CWDebugLog(\"Failure sending Request\");\n            int k;\n            for(k = 0; k < gPendingRequestMsgs[arg].fragmentsNum; k++) {\n                CW_FREE_PROTOCOL_MESSAGE(gPendingRequestMsgs[arg].msgElems[k]);\n            }\n            CW_FREE_OBJECT(gPendingRequestMsgs[arg].msgElems);\n            CWThreadSetSignals(SIG_UNBLOCK, 1, SIGALRM);\n            return;\n        }\n    }\n    gPendingRequestMsgs[arg].retransmission++;\n\n    if(!CWTimerCreate(gPendingRequestMsgs[arg].timer_sec, &(gPendingRequestMsgs[arg].timer), gPendingRequestMsgs[arg].timer_hdl, gPendingRequestMsgs[arg].timer_arg)) {\n        CWThreadSetSignals(SIG_UNBLOCK, 1, SIGALRM);\n        return;\n    }\n\n    CWThreadSetSignals(SIG_UNBLOCK, 1, SIGALRM);\n\n    return;\n}\n*/\n\nvoid CWWTPRetransmitTimerExpiredHandler(CWTimerArg hdl_arg)\n{\n\tint index = *((int *)hdl_arg);\n\n\tCWDebugLog(\"Retransmit Timer Expired for Thread: %08x\", (unsigned int)CWThreadSelf());\n\n\tif (gPendingRequestMsgs[index].retransmission == gCWMaxRetransmit) {\n\t\tCWDebugLog(\"Peer is Dead\");\n\t\t//_CWCloseThread(*iPtr);\n\t\treturn;\n\t}\n\n\tCWDebugLog(\"Retransmission Count increases to %d\", gPendingRequestMsgs[index].retransmission);\n\n\tint i;\n\tfor (i = 0; i < gPendingRequestMsgs[index].fragmentsNum; i++) {\n#ifdef CW_NO_DTLS\n\t\tif (!CWNetworkSendUnsafeConnected(gWTPSocket,\n\t\t\t\t\t\t  gPendingRequestMsgs[index].msgElems[i].msg,\n\t\t\t\t\t\t  gPendingRequestMsgs[index].msgElems[i].offset)) {\n#else\n\t\tif (!CWSecuritySend(gWTPSession,\n\t\t\t\t    gPendingRequestMsgs[index].msgElems[i].msg,\n\t\t\t\t    gPendingRequestMsgs[index].msgElems[i].offset)) {\n#endif\n\t\t\tCWDebugLog(\"Failure sending Request\");\n\t\t\tint k;\n\t\t\tfor (k = 0; k < gPendingRequestMsgs[index].fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(gPendingRequestMsgs[index].msgElems[k]);\n\t\t\t}\n\t\t\tCW_FREE_OBJECT(gPendingRequestMsgs[index].msgElems);\n\t\t\tCW_FREE_OBJECT(hdl_arg);\n\t\t\treturn;\n\t\t}\n\t}\n\tgPendingRequestMsgs[index].retransmission++;\n\n\tgPendingRequestMsgs[index].timer = timer_add(gPendingRequestMsgs[index].timer_sec,\n\t\t\t\t\t\t     0,\n\t\t\t\t\t\t     gPendingRequestMsgs[index].timer_hdl,\n\t\t\t\t\t\t     gPendingRequestMsgs[index].timer_arg);\n\tCW_FREE_OBJECT(hdl_arg);\n\treturn;\n}\n"
  },
  {
    "path": "WTPSettingsFile.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWCommon.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define CW_SETTINGS_FILE    \"settings.wtp.txt\"\n\nFILE *gSettingsFile = NULL;\nchar *gInterfaceName = NULL;\nchar *gEthInterfaceName = NULL;\nchar *gRadioInterfaceName_0 = NULL;\nchar *gBaseMACInterfaceName = NULL;\nchar gBoardReversionNo;\n\nint gHostapd_port;\nchar *gHostapd_unix_path;\n\nvoid CWExtractValue(char *start, char **startValue, char **endValue, int *offset)\n{\n\t*offset = strspn(start + 1, \" \\t\\n\\r\");\n\t*startValue = start + 1 + *offset;\n\n\t*offset = strcspn(*startValue, \" \\t\\n\\r\");\n\t*endValue = *startValue + *offset - 1;\n}\n\nCWBool CWParseSettingsFile()\n{\n\tchar *line = NULL;\n\n\tgSettingsFile = fopen(CW_SETTINGS_FILE, \"rb\");\n\tif (gSettingsFile == NULL) {\n\t\tCWErrorRaiseSystemError(CW_ERROR_GENERAL);\n\t}\n\n\twhile ((line = (char *)CWGetCommand(gSettingsFile)) != NULL) {\n\t\tchar *startTag = NULL;\n\t\tchar *endTag = NULL;\n\n\t\tif ((startTag = strchr(line, '<')) == NULL) {\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ((endTag = strchr(line, '>')) == NULL) {\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"IF_NAME\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tCW_CREATE_STRING_ERR(gInterfaceName, offset, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tstrncpy(gInterfaceName, startValue, offset);\n\t\t\tgInterfaceName[offset] = '\\0';\n\t\t\tCWLog(\": %s\", gInterfaceName);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"WTP_ETH_IF_NAME\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tCW_CREATE_STRING_ERR(gEthInterfaceName, offset,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tstrncpy(gEthInterfaceName, startValue, offset);\n\t\t\tgEthInterfaceName[offset] = '\\0';\n\t\t\tCWLog(\": %s\", gEthInterfaceName);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"RADIO_0_IF_NAME\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tCW_CREATE_STRING_ERR(gRadioInterfaceName_0, offset,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tstrncpy(gRadioInterfaceName_0, startValue, offset);\n\t\t\tgRadioInterfaceName_0[offset] = '\\0';\n\t\t\tCWLog(\": %s\", gRadioInterfaceName_0);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"BASE_MAC_IF_NAME\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tCW_CREATE_STRING_ERR(gBaseMACInterfaceName, offset,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tstrncpy(gBaseMACInterfaceName, startValue, offset);\n\t\t\tgBaseMACInterfaceName[offset] = '\\0';\n\t\t\tCWLog(\": %s\", gBaseMACInterfaceName);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!strncmp(startTag + 1, \"BOARD_REVISION_NO\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\t\t\tchar reversion[16];\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tstrncpy(reversion, startValue, offset);\n\t\t\treversion[offset] = '\\0';\n\t\t\tgBoardReversionNo = atoi(reversion);\n\t\t\tCWLog(\": %d\", gBoardReversionNo);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"WTP_HOSTAPD_PORT\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\t\t\tchar port_str[16];\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tstrncpy(port_str, startValue, offset);\n\t\t\tport_str[offset] = '\\0';\n\t\t\tgHostapd_port = atoi(port_str);\n\t\t\tCWLog(\": %d\", gHostapd_port);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!strncmp(startTag + 1, \"WTP_HOSTAPD_UNIX_PATH\", endTag - startTag - 1)) {\n\t\t\tchar *startValue = NULL;\n\t\t\tchar *endValue = NULL;\n\t\t\tint offset = 0;\n\n\t\t\tCWExtractValue(endTag, &startValue, &endValue, &offset);\n\n\t\t\tCW_CREATE_STRING_ERR(gHostapd_unix_path, offset,\n\t\t\t\t\t     return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);\n\t\t\t    );\n\t\t\tstrncpy(gHostapd_unix_path, startValue, offset);\n\t\t\tgHostapd_unix_path[offset] = '\\0';\n\t\t\tCWLog(\": %s\", gHostapd_unix_path);\n\t\t\tCW_FREE_OBJECT(line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tCW_FREE_OBJECT(line);\n\t}\n\treturn CW_TRUE;\n}\n"
  },
  {
    "path": "WTPStatsReceive.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2008 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author : Daniele De Sanctis (danieledesanctis@gmail.com)                                *\n *                                                                     *\n *******************************************************************************************/\n\n#include \"WTPStatsReceive.h\"\n\nint create_data_Frame(CWProtocolMessage ** frame, char *buffer, int len)\n{\n\n\tCW_CREATE_OBJECT_ERR(*frame, CWProtocolMessage, return 0;\n\t    );\n\tCWProtocolMessage *auxPtr = *frame;\n\tCW_CREATE_PROTOCOL_MESSAGE(*auxPtr, len, return 0;\n\t    );\n\tmemcpy(auxPtr->msg, buffer, len);\n\tauxPtr->offset = len;\n\treturn 1;\n}\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveStats(void *arg)\n{\n\n\tint sock, rlen, len, k, fragmentsNum = 0, fromlen;\n\tMM_MONITOR_DATA *pData;\n\tstruct sockaddr_un servaddr;\n\tstruct sockaddr_un from;\n\tstatic char buffer[PACKET_SIZE + 1];\n\tCWProtocolMessage *completeMsgPtr = NULL;\n\tCWProtocolMessage *data = NULL;\n\tCWBindingTransportHeaderValues *bindingValuesPtr = NULL;\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n\t/*      Create a UNIX datagram socket for this thread        */\n\tif ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {\n\t\tCWDebugLog(\"THR STATS: Error creating socket\");\n\t\tCWExitThread();\n\t}\n\n\t/*      Set up address structure for server socket      */\n\tbzero(&servaddr, sizeof(servaddr));\n\tbzero(&from, sizeof(from));\n\tservaddr.sun_family = AF_UNIX;\n\tstrcpy(servaddr.sun_path, SOCKET_PATH);\n\n\tunlink(SOCKET_PATH);\n\n\tlen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);\n\n\tif (bind(sock, (const struct sockaddr *)&servaddr, len) < 0) {\n\t\tCWDebugLog(\"THR STATS: Error binding socket\");\n\t\tCWExitThread();\n\t}\n\n\tCW_CREATE_OBJECT_ERR(pData, MM_MONITOR_DATA, EXIT_THREAD);\n\tfromlen = sizeof(from);\n\n\t/*      Receive data */\n\tCW_REPEAT_FOREVER {\n\t\trlen = recvfrom(sock, buffer, PACKET_SIZE, 0, (struct sockaddr *)&from, (socklen_t *) & fromlen);\n\t\tif (rlen == -1) {\n\t\t\tCWDebugLog(\"THR STATS: Error receiving from unix socket\");\n\t\t\tCWExitThread();\n\t\t} else {\n\t\t\tcompleteMsgPtr = NULL;\n\n\t\t\tif (!create_data_Frame(&data, buffer, rlen)) {\n\t\t\t\tCWDebugLog(\"Error extracting a data stats frame\");\n\t\t\t\tCWExitThread();\n\t\t\t};\n\n\t\t\tpData = (MM_MONITOR_DATA *) data->msg;\n\n\t\t\tCW_CREATE_OBJECT_ERR(bindingValuesPtr, CWBindingTransportHeaderValues, EXIT_THREAD);\n\t\t\tbindingValuesPtr->dataRate = -1;\t//to distinguish between wireless frame e data message (Daniele) see CWBindig.c line 224\n\n\t\t\tif (CWAssembleDataMessage(&completeMsgPtr, &fragmentsNum, gWTPPathMTU, data, bindingValuesPtr,\n\t\t\t\t\t\t  CW_PACKET_PLAIN, 0)) {\n\t\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n#ifdef CW_NO_DTLS\n\t\t\t\t\tif (!CWNetworkSendUnsafeConnected\n\t\t\t\t\t    (gWTPSocket, completeMsgPtr[k].msg, completeMsgPtr[k].offset)) {\n#else\n\t\t\t\t\tif (!CWSecuritySend\n\t\t\t\t\t    (gWTPSession, completeMsgPtr[k].msg, completeMsgPtr[k].offset)) {\n#endif\n\t\t\t\t\t\tCWDebugLog(\"Failure sending Request\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (k = 0; k < fragmentsNum; k++) {\n\t\t\t\tCW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]);\n\t\t\t}\n\n\t\t\tCW_FREE_OBJECT(completeMsgPtr);\n\t\t\tCW_FREE_OBJECT(data);\n\t\t\tCW_FREE_OBJECT(bindingValuesPtr);\n\t\t}\n\n\t}\n\n\tclose(sock);\n\treturn (NULL);\n}\n"
  },
  {
    "path": "WTPStatsReceive.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2008 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author : Daniele De Sanctis (danieledesanctis@gmail.com)                                *\n *                                                                     *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_WTPStatsReceive_HEADER__\n#define __CAPWAP_WTPStatsReceive_HEADER__\n\n#include \"CWWTP.h\"\n#include <ctype.h>\n#include <netinet/in.h>\n#include <sys/un.h>\n\n#define SOCKET_PATH     \"/tmp/wtp\"\n#define PACKET_SIZE                     65536\n\n#define EXIT_THREAD     CWLog(\"ERROR Handling Stats: application will be closed!\");     \\\n                close(sock);                                \\\n                exit(1);\n\n//////////////////// copy of ath_clone.h ////////////////////////////////////////////////////////\n/*\n * Ioctl-related defintions for the Atheros Wireless LAN controller driver.\n */\n\n#ifndef WME_AC_BE\n#define WME_AC_BE                       0\n#endif\n#ifndef WME_AC_BK\n#define WME_AC_BK                       1\n#endif\n#ifndef WME_AC_VI\n#define WME_AC_VI                       2\n#endif\n#ifndef WME_AC_VO\n#define WME_AC_VO                       3\n#endif\n\n#ifndef WME_NUM_AC\n#define WME_NUM_AC                      4\n#endif\n\n#ifndef u_int32_t\n#define u_int32_t           unsigned long\n#endif\n\n#ifndef u_int16_t\n#define u_int16_t           unsigned short\n#endif\n\n#ifndef u_int8_t\n#define u_int8_t            unsigned char\n#endif\n\n#ifndef int8_t\n#define int8_t              char\n#endif\n\nstruct ath_stats_wme_clone {\n\tu_int32_t tx_packetscount;\n\tu_int32_t tx_packetslen;\n\tu_int32_t rx_packetscount;\n\tu_int32_t rx_packetslen;\n\tu_int32_t tx_shortretry;\t/* tx on-chip retries (short) */\n\tu_int32_t tx_longretry;\t/* tx on-chip retries (long) */\n\tu_int32_t tx_pending;\t/* tx packet pending */\n\tu_int32_t tx_queue;\t/* tx packet queue */\n\tu_int32_t tx_totalqueued;\t/* tx packet total queued */\n\tu_int32_t tx_failed;\t/* tx packet failed */\n\tu_int32_t tx_discard;\t/* tx packet discard */\n\tu_int8_t wme_chan_logcwmin;\t/* cwmin in exponential form */\n\tu_int8_t wme_chan_logcwmax;\t/* cwmax in exponential form */\n\tu_int8_t wme_chan_aifsn;\t/* AIFSN parameters */\n\tu_int16_t wme_chan_txopLimit;\t/* txopLimit */\n\tu_int8_t wme_bss_logcwmin;\t/* cwmin in exponential form */\n\tu_int8_t wme_bss_logcwmax;\t/* cwmax in exponential form */\n\tu_int8_t wme_bss_aifsn;\t/* AIFSN parameters */\n\tu_int16_t wme_bss_txopLimit;\t/* txopLimit */\n};\n\nstruct ath_stats_clone {\n\tu_int32_t ast_watchdog;\t/* device reset by watchdog */\n\tu_int32_t ast_hardware;\t/* fatal hardware error interrupts */\n\tu_int32_t ast_bmiss;\t/* beacon miss interrupts */\n\tu_int32_t ast_rxorn;\t/* rx overrun interrupts */\n\tu_int32_t ast_rxeol;\t/* rx eol interrupts */\n\tu_int32_t ast_txurn;\t/* tx underrun interrupts */\n\tu_int32_t ast_mib;\t/* mib interrupts */\n\tu_int32_t ast_tx_packets;\t/* packet sent on the interface */\n\tu_int32_t ast_tx_bytes;\t/* total bytes transmitted */\n\tu_int32_t ast_tx_mgmt;\t/* management frames transmitted */\n\tu_int32_t ast_tx_discard;\t/* frames discarded prior to assoc */\n\tu_int32_t ast_tx_invalid;\t/* frames discarded due to is device gone */\n\tu_int32_t ast_tx_qstop;\t/* tx queue stopped because it's full */\n\tu_int32_t ast_tx_encap;\t/* tx encapsulation failed */\n\tu_int32_t ast_tx_nonode;\t/* tx failed due to of no node */\n\tu_int32_t ast_tx_nobuf;\t/* tx failed due to of no tx buffer (data) */\n\tu_int32_t ast_tx_nobufmgt;\t/* tx failed due to of no tx buffer (mgmt) */\n\tu_int32_t ast_tx_xretries;\t/* tx failed due to of too many retries */\n\tu_int32_t ast_tx_fifoerr;\t/* tx failed due to of FIFO underrun */\n\tu_int32_t ast_tx_filtered;\t/* tx failed due to xmit filtered */\n\tu_int32_t ast_tx_shortretry;\t/* tx on-chip retries (short) */\n\tu_int32_t ast_tx_longretry;\t/* tx on-chip retries (long) */\n\tu_int32_t ast_tx_badrate;\t/* tx failed due to of bogus xmit rate */\n\tu_int32_t ast_tx_noack;\t/* tx frames with no ack marked */\n\tu_int32_t ast_tx_rts;\t/* tx frames with rts enabled */\n\tu_int32_t ast_tx_cts;\t/* tx frames with cts enabled */\n\tu_int32_t ast_tx_shortpre;\t/* tx frames with short preamble */\n\tu_int32_t ast_tx_altrate;\t/* tx frames with alternate rate */\n\tu_int32_t ast_tx_protect;\t/* tx frames with protection */\n\tu_int32_t ast_rx_orn;\t/* rx failed due to of desc overrun */\n\tu_int32_t ast_rx_crcerr;\t/* rx failed due to of bad CRC */\n\tu_int32_t ast_rx_fifoerr;\t/* rx failed due to of FIFO overrun */\n\tu_int32_t ast_rx_badcrypt;\t/* rx failed due to of decryption */\n\tu_int32_t ast_rx_badmic;\t/* rx failed due to of MIC failure */\n\tu_int32_t ast_rx_phyerr;\t/* rx PHY error summary count */\n\tu_int32_t ast_rx_phy[32];\t/* rx PHY error per-code counts */\n\tu_int32_t ast_rx_tooshort;\t/* rx discarded due to frame too short */\n\tu_int32_t ast_rx_toobig;\t/* rx discarded due to frame too large */\n\tu_int32_t ast_rx_nobuf;\t/* rx setup failed due to of no skbuff */\n\tu_int32_t ast_rx_packets;\t/* packet recv on the interface */\n\tu_int32_t ast_rx_bytes;\t/* total bytes received */\n\tu_int32_t ast_rx_mgt;\t/* management frames received */\n\tu_int32_t ast_rx_ctl;\t/* control frames received */\n\tint8_t ast_tx_rssi;\t/* tx rssi of last ack */\n\tint8_t ast_rx_rssi;\t/* rx rssi from histogram */\n\tu_int32_t ast_be_xmit;\t/* beacons transmitted */\n\tu_int32_t ast_be_nobuf;\t/* no skbuff available for beacon */\n\tu_int32_t ast_per_cal;\t/* periodic calibration calls */\n\tu_int32_t ast_per_calfail;\t/* periodic calibration failed */\n\tu_int32_t ast_per_rfgain;\t/* periodic calibration rfgain reset */\n\tu_int32_t ast_rate_calls;\t/* rate control checks */\n\tu_int32_t ast_rate_raise;\t/* rate control raised xmit rate */\n\tu_int32_t ast_rate_drop;\t/* rate control dropped xmit rate */\n\tu_int32_t ast_ant_defswitch;\t/* rx/default antenna switches */\n\tu_int32_t ast_ant_txswitch;\t/* tx antenna switches */\n\tu_int32_t ast_ant_rx[8];\t/* rx frames with antenna */\n\tu_int32_t ast_ant_tx[8];\t/* tx frames with antenna */\n\tstruct ath_stats_wme_clone ast_wme[WME_NUM_AC];\n};\n\n//////////////////// copy of ath-monitor.h ////////////////////////////////////////////////////////\n\n/* Monitoraggio dei dati dell'interfaccia di rete */\ntypedef struct _MM_MONITOR_DATA {\n\tint nInterfaceId;\n\tstruct timeval timeData;\n\tunsigned long nInputFrame;\n\tunsigned long nInputBandwidth;\n\tunsigned long nOutputFrame;\n\tunsigned long nOutputBandwidth;\n\tstruct ath_stats_clone athCurrentStats;\n} MM_MONITOR_DATA;\n\nint create_data_Frame(CWProtocolMessage ** frame, char *buffer, int len);\n#endif\n"
  },
  {
    "path": "WTPSulkingState.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"CWWTP.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#ifdef CW_DEBUGGING\nint gCWSilentInterval = 5;\n#else\nint gCWSilentInterval = 30;\n#endif\n\n/*\n * WTP enters sulking when no AC is responding to Discovery Request.\n */\nCWStateTransition CWWTPEnterSulking()\n{\n\tstruct timeval timeout, before, after, delta, newTimeout;\n\n\tCWLog(\"\\n\");\n\tCWLog(\"######### Sulking State #########\");\n\t/*\n\t * wait for Silent Interval and discard\n\t * all the packets that are coming\n\t */\n\ttimeout.tv_sec = newTimeout.tv_sec = gCWSilentInterval;\n\ttimeout.tv_usec = newTimeout.tv_usec = 0;\n\n\tgettimeofday(&before, NULL);\n\n\tCW_REPEAT_FOREVER {\n\n\t\t/* check if something is available to read until newTimeout */\n\t\tif (CWNetworkTimedPollRead(gWTPSocket, &newTimeout)) {\n\t\t\t/*\n\t\t\t * success\n\t\t\t * if there was no error, raise a \"success error\", so we can easily handle\n\t\t\t * all the cases in the switch\n\t\t\t */\n\t\t\tCWErrorRaise(CW_ERROR_SUCCESS, NULL);\n\t\t}\n\n\t\tswitch (CWErrorGetLastErrorCode()) {\n\t\tcase CW_ERROR_TIME_EXPIRED:\n\t\t\tgoto cw_sulk_time_over;\n\t\t\tbreak;\n\t\tcase CW_ERROR_SUCCESS:\n\t\t\t/* there's something to read */\n\t\t\t{\n\t\t\t\tCWNetworkLev4Address addr;\n\t\t\t\tunsigned char buf[CW_BUFFER_SIZE];\n\t\t\t\tint readBytes;\n\n\t\t\t\t/* read and discard */\n\t\t\t\tif (!CWErr\n\t\t\t\t    (CWNetworkReceiveUnsafe(gWTPSocket, buf, CW_BUFFER_SIZE, 0, &addr, &readBytes))) {\n\t\t\t\t\treturn CW_QUIT;\n\t\t\t\t}\n\t\t\t}\n\t\tcase CW_ERROR_INTERRUPTED:\n\t\t\t/*\n\t\t\t *  something to read OR interrupted by the\n\t\t\t *  system\n\t\t\t *  wait for the remaining time (NetworkPoll\n\t\t\t *  will be recalled with the remaining time)\n\t\t\t */\n\t\t\tgettimeofday(&after, NULL);\n\n\t\t\tCWTimevalSubtract(&delta, &after, &before);\n\t\t\tif (CWTimevalSubtract(&newTimeout, &timeout, &delta) == 1) {\n\t\t\t\t/* negative delta: time is over */\n\t\t\t\tgoto cw_sulk_time_over;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tCWErrorHandleLast();\n\t\t\tgoto cw_error;\n\t\t\tbreak;\n\t\t}\n\t}\n cw_sulk_time_over:\n\tCWLog(\"End of Sulking Period\");\n cw_error:\n\treturn CW_ENTER_DISCOVERY;\n}\n"
  },
  {
    "path": "WTPipcHostapd.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Sotiraq Sima (Sotiraq.Sima@gmail.com)                                         *\n *                                                                                         *\n *******************************************************************************************/\n#include <netinet/in.h>\n\n#include \"WTPipcHostapd.h\"\n#include \"WTPmacFrameReceive.h\"\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define EXIT_FRAME_THREAD(sock) CWLog(\"ERROR Handling Frames: application will be closed!\"); close(sock); exit(1);\n\n//#define LOCALUDP\n//#define NETUDP\n//#define NETSEQ\n\n//#define USEIPV6\n\nsocklen_t address_size;\n\n#if defined(LOCALUDP)\nstruct sockaddr_un client;\n#else\n#if defined(USEIPV6)\nstruct sockaddr_in6 client;\n#else\nstruct sockaddr_in client;\n#endif\n\n#endif\n\nchar connected = 0;\nint sock;\nextern int wtpInRunState;\npthread_mutex_t gRADIO_MAC_mutex;\npthread_mutex_t mutext_info;\n\nunsigned char WTP_Radio_Information = 0;\nunsigned char WTP_Rates[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };\nunsigned char WTP_MDC[6] = { 0, 0, 0, 0, 0, 0 };\n\nunsigned char gRADIO_MAC[6];\n\nint flush_pcap(u_char * buf, int len, char *filename)\n{\n\treturn 0;\n\n\tFILE *file;\n\tfile = fopen(filename, \"a+\");\n\tu_char index = 0x00;\n\tint cnt = 0;\n\tint i;\n\tint giro = 0;\n\tfor (i = 0; cnt < len; i++) {\n\t\tfprintf(file, \"0%02X0   \", index);\n\t\tfor (; cnt < len;) {\n\t\t\tfprintf(file, \"%02X \", buf[cnt]);\n\t\t\tcnt++;\n\t\t\tif (giro == 15) {\n\t\t\t\tgiro = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgiro++;\n\t\t}\n\t\tfprintf(file, \"\\n\");\n\t\tindex++;\n\t}\n\n\tfprintf(file, \"\\n\");\n\tfclose(file);\n\treturn 0;\n}\n\nvoid CWWTP_get_WTP_Rates(unsigned char *buf)\n{\n\n\tCWThreadMutexLock(&mutext_info);\n\tmemcpy(buf, WTP_Rates, 8);\n\tCWThreadMutexUnlock(&mutext_info);\n\n}\n\nvoid CWWTP_get_WTP_MDC(unsigned char *buf)\n{\n\n\tCWThreadMutexLock(&mutext_info);\n\tmemcpy(buf, WTP_MDC, 6);\n\tCWThreadMutexUnlock(&mutext_info);\n\n}\n\nunsigned char CWTP_get_WTP_Radio_Information()\n{\n\n\tunsigned char tmp_info;\n\tCWThreadMutexLock(&mutext_info);\n\ttmp_info = WTP_Radio_Information;\n\tCWThreadMutexUnlock(&mutext_info);\n\treturn tmp_info;\n\n}\n\nvoid CWWTPsend_data_to_hostapd(unsigned char *buf, int len)\n{\n\n\tif (!connected)\n\t\treturn;\n\n\tunsigned char tmp_buf[CW_BUFFER_SIZE];\n\ttmp_buf[0] = DATE_TO_WTP;\n\tmemcpy(tmp_buf + 1, buf, len);\n\n\tif (sendto(sock, tmp_buf, len + 1, 0, (struct sockaddr *)&client, address_size) < 0) {\n\t\tCWDebugLog(\"Error to send data frame on Unix socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWWTPsend_command_to_hostapd_SET_TXQ(unsigned char *buf, int len)\n{\n\n\tif (!connected)\n\t\treturn;\n\tbuf[0] = SET_TXQ;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on Unix socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWWTPsend_command_to_hostapd_SET_ADDR(unsigned char *buf, int len)\n{\n\n\tif (!connected)\n\t\treturn;\n\tbuf[0] = SET_ADDR;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWWTPsend_command_to_hostapd_ADD_WLAN(unsigned char *buf, int len)\n{\n\tCWDebugLog(\"CWWTPsend_command_to_hostapd_ADD_WLAN()\");\n WAITHOSTAPDADD:\n\n\tif (!connected) {\n\t\tsleep(0.2);\n\t\tgoto WAITHOSTAPDADD;\n\t}\n\tbuf[0] = ADD_WLAN;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size) < 0) {\n\t\tCWDebugLog(\"Error to send command ADD WLAN on socket\");\n\t\treturn;\n\t}\n}\n\nvoid CWWTPsend_command_to_hostapd_DEL_WLAN(unsigned char *buf, int len)\n{\n\n WAITHOSTAPDDEL:\n\n\tif (!connected) {\n\t\tsleep(0.2);\n\t\tgoto WAITHOSTAPDDEL;\n\t}\n\tbuf[0] = DEL_WLAN;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size) < 0) {\n\t\tCWLog(\"Error to send command DEL WLAN on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWWTPsend_command_to_hostapd_DEL_ADDR(unsigned char *buf, int len)\n{\n\n\tif (!connected)\n\t\treturn;\n\tbuf[0] = DEL_ADDR;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size) < 0) {\n\t\tCWLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nvoid CWWTPsend_command_to_hostapd_CLOSE(unsigned char *buf, int len)\n{\n\n\tbuf[0] = CLOSE;\n\n\tif (sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size) < 0) {\n\t\tCWLog(\"Error to send command frame on socket\");\n\t\treturn;\n\t}\n\n}\n\nCW_THREAD_RETURN_TYPE CWWTPThread_read_data_from_hostapd(void *arg)\n{\n\t/*\n\t   CWThreadMutexLock(&gRADIO_MAC_mutex);\n\t   gRADIO_MAC[0]=0xAA;\n\t   gRADIO_MAC[1]=0xBB;\n\t   gRADIO_MAC[2]=0xCC;\n\t   gRADIO_MAC[3]=0xDD;\n\t   gRADIO_MAC[4]=0xEE;\n\t   gRADIO_MAC[5]=0xFF;\n\t   CWThreadMutexUnlock(&gRADIO_MAC_mutex);\n\t*/\n\tint len;\n\n\n#if defined(LOCALUDP)\n\tstruct sockaddr_un server;\n#else\n#if defined(USEIPV6)\n\tstruct sockaddr_in6 server;\n#else\n\tstruct sockaddr_in server;\n#endif\n#endif\n\n\tunsigned char buffer[CW_BUFFER_SIZE];\n\tint connect_ret;\n\tunsigned char cmd[10];\n\n\tCWProtocolMessage *frame = NULL;\n\tCWBindingDataListElement *listElement = NULL;\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n#if defined(LOCALUDP)\n\tsock = socket(AF_UNIX, SOCK_DGRAM, 0);\n\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tbzero(&server, sizeof(server));\n\tsock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);\n#else\n\tmemset(&server, 0, sizeof(server));\n\tsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n#endif\n\n#else\n#if defined(USEIPV6)\n\tbzero(&server, sizeof(server));\n\tsock = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);\n#else\n\tmemset(&server, 0, sizeof(server));\n\tsock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);\n#endif\n\n#endif\n\n\tif (sock < 0) {\n\t\tCWDebugLog(\"WTP ipc HOSTAPD: Error creating socket\");\n\t\tEXIT_FRAME_THREAD(sock);\n\t}\n\n\tCWDebugLog(\"WTP ipc HOSTAPD: Trying to connect to hostapd (wtp)...\");\n\n#if defined(LOCALUDP)\n\tserver.sun_family = AF_UNIX;\n\tstrcpy(server.sun_path, gHostapd_unix_path);\n\tunlink(server.sun_path);\n\n\tconnect_ret = bind(sock, (struct sockaddr *)&server, strlen(server.sun_path) + sizeof(server.sun_family));\n\n\tclient.sun_family = AF_UNIX;\n\n#else\n#if defined(USEIPV6)\n\tserver.sin6_family = AF_INET6;\n\tserver.sin6_port = gHostapd_port;\n\tserver.sin6_addr = in6addr_any;\n#else\n\tserver.sin_family = AF_INET;\n\tserver.sin_port = gHostapd_port;\n\tserver.sin_addr.s_addr = INADDR_ANY;\n#endif\n\tconnect_ret = bind(sock, (struct sockaddr *)&server, sizeof(server));\n\n#endif\n\n\tif (connect_ret == -1) {\n\t\tCWDebugLog(\"WTP ipc HOSTAPD: Error connect/bind to socket\");\n\t\tEXIT_FRAME_THREAD(sock);\n\t}\n#if defined(LOCALUDP)\n\n#elif defined(NETUDP)\n\n#else\n\t/* 1: Only one daemon Hostapd_WTP at time */\n\tif (listen(sock, 1) < 0) {\n\t\tCWDebugLog(\"WTP ipc HOSTAPD: Error listen \");\n\t\tEXIT_FRAME_THREAD(sock);\n\t}\n#endif\n\n#if defined(LOCALUDP)\n\tCWDebugLog(\"Waiting packet from Hostapd_WTP at Pipe:%s\", gHostapd_unix_path);\n#else\n\tCWDebugLog(\"Waiting packet from Hostapd_WTP at Port:%d\", gHostapd_port);\n#endif\n\n        client.sin_family = AF_INET;\n        client.sin_addr.s_addr = inet_addr(\"127.0.0.1\");\n        client.sin_port = htons(6444);\n\n\taddress_size = sizeof(client);\n\n\tint sig_byte = 1;\n\n#if defined(LOCALUDP)\n\tsig_byte += 5;\n#endif\n\n        CWDebugLog(\"Checking if hostapd is started already\");\n        cmd[0] = CONNECT_R;\n        sendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n        cmd[0] = WTPRINFO;      //Next info to get\n        sendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n\n\tCW_REPEAT_FOREVER {\n\n\t\tlen = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&client, &address_size);\n\n#if defined(LOCALUDP)\n\t\tsprintf(client.sun_path, \"%s%c%c%c%c%c\", server.sun_path, buffer[1], buffer[2], buffer[3], buffer[4],\n\t\t\tbuffer[5]);\n#endif\n\n\t\tif (len <= 0) {\n\t\t\tEXIT_FRAME_THREAD(sock)\n\t\t}\n\n\t\tif (connected == 0 && buffer[0] != CONNECT && buffer[0] != WTPRINFO_R) {\n\t\t\tCWDebugLog(\"IPC packet - WTP is not in RUN state\");\n\t\t\tCWWTPsend_command_to_hostapd_CLOSE(cmd, 10);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (buffer[0] == DATE_TO_AC) {\n\n\t\t\tif (!wtpInRunState)\n\t\t\t\tcontinue;\n\n\t\t\tif (!extract802_11_Frame(&frame, buffer + sig_byte, len - sig_byte)) {\n\t\t\t\tCWLog(\"THR FRAME: Error extracting a frame\");\n\t\t\t\tEXIT_FRAME_THREAD(sock);\n\t\t\t}\n\n\t\t\tCWDebugLog(\"Send 802.11 management(len:%d) to AC\", len - 1);\n\n\t\t\tCW_CREATE_OBJECT_ERR(listElement, CWBindingDataListElement, EXIT_FRAME_THREAD(sock);\n\t\t\t    );\n\t\t\tlistElement->frame = frame;\n\t\t\tlistElement->bindingValues = NULL;\n\n\t\t\tlistElement->frame->data_msgType = CW_IEEE_802_11_FRAME_TYPE;\n\n\t\t\tCWLockSafeList(gFrameList);\n\t\t\tCWAddElementToSafeListTail(gFrameList, listElement, sizeof(CWBindingDataListElement));\n\t\t\tCWUnlockSafeList(gFrameList);\n\n\t\t} else if (buffer[0] == CONNECT) {\n\n\t\t\tconnected = 1;\n\t\t\tcmd[0] = CONNECT_R;\n\t\t\tsendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n\n\t\t\tcmd[0] = WTPRINFO;\t//Next info to get\n\t\t\tsendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n\n\t\t} else if (buffer[0] == WTPRINFO_R) {\n\t\t\tconnected = 1;\n\n#if defined(LOCALUDP)\n                        CWDebugLog(\"Hostapd_wtp Unix Domain Connect: %s\", client.sun_path);\n#else\n#if defined(USEIPV6)\n                        CWDebugLog(\"Hostapd_wtp (v6) Connect: %d\", client.sin6_port);\n#else\n                        CWDebugLog(\"Hostapd_wtp (v4) Connect: %s:%d\", inet_ntoa(client.sin_addr), client.sin_port);\n#endif\n#endif\n\n\t\t\tCWThreadMutexLock(&mutext_info);\n\t\t\tmemcpy(&WTP_Radio_Information, buffer + sig_byte, 1);\n\t\t\tCWThreadMutexUnlock(&mutext_info);\n\n\t\t\tCWDebugLog(\"WTPRINFO_R:  %02X\", WTP_Radio_Information);\n\n\t\t\tcmd[0] = GET_RATES;\t//Next info to get\n\t\t\tsendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n\n\t\t} else if (buffer[0] == GET_RATES_R) {\n\n\t\t\tCWThreadMutexLock(&mutext_info);\n\t\t\tmemcpy(WTP_Rates, buffer + sig_byte, 8);\n\t\t\tCWThreadMutexUnlock(&mutext_info);\n\n\t\t\tCWDebugLog(\"GET_RATES_R:   %02X  %02X  %02X  %02X  %02X  %02X  %02X  %02X\", WTP_Rates[0],\n\t\t\t\t   WTP_Rates[1], WTP_Rates[2], WTP_Rates[3], WTP_Rates[4], WTP_Rates[5], WTP_Rates[6],\n\t\t\t\t   WTP_Rates[7]);\n\n\t\t\tcmd[0] = GET_MDC;\t//Next info to get\n\t\t\tsendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n\n\t\t} else if (buffer[0] == GET_MDC_R) {\n\n\t\t\tCWThreadMutexLock(&mutext_info);\n\t\t\tmemcpy(WTP_MDC, buffer + sig_byte, 6);\n\t\t\tCWThreadMutexUnlock(&mutext_info);\n\n\t\t\tCWDebugLog(\"GET_MDC_R: %02X  %02X  %02X  %02X  %02X  %02X\",\n\t\t\t\t   WTP_MDC[0], WTP_MDC[1], WTP_MDC[2], WTP_MDC[3], WTP_MDC[4], WTP_MDC[5]);\n\n\t\t\tcmd[0] = GET_MAC;\n\t\t\tsendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n\n\t\t} else if (buffer[0] == GET_MAC_R) {\n\n\t\t\tCWThreadMutexLock(&gRADIO_MAC_mutex);\n\t\t\tmemcpy(gRADIO_MAC, buffer + sig_byte, 6);\n\t\t\tCWThreadMutexUnlock(&gRADIO_MAC_mutex);\n\n\t\t\tCWDebugLog(\"GET_MAC_R:   %02X  %02X  %02X  %02X  %02X  %02X\",\n\t\t\t\t   (unsigned char)gRADIO_MAC[0],\n\t\t\t\t   (unsigned char)gRADIO_MAC[1],\n\t\t\t\t   (unsigned char)gRADIO_MAC[2],\n\t\t\t\t   (unsigned char)gRADIO_MAC[3],\n\t\t\t\t   (unsigned char)gRADIO_MAC[4], (unsigned char)gRADIO_MAC[5]);\n\n\t\t\tcmd[0] = GOWAITWLAN;\n\t\t\tsendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size);\n\n\t\t} else if (buffer[0] == CLOSE) {\n\n\t\t\tconnected = 0;\n#if defined(LOCALUDP)\n\t\t\tCWDebugLog(\"Hostapd_wtp Unix Domain DisConnect: %s\", client.sun_path);\n#else\n#if defined(USEIPV6)\n\t\t\tCWDebugLog(\"Hostapd_wtp (v6) DisConnect: %d\", client.sin6_port);\n#else\n\t\t\tCWDebugLog(\"Hostapd_wtp (v4) Disconnect: %s:%d\", inet_ntoa(client.sin_addr), client.sin_port);\n#endif\n#endif\n\n\t\t} else if (buffer[0] == SET_TXQ_R) {\n\n\t\t\tCWDebugLog(\"Hostapd WTP \\\"SET_TXQ_R\\\" Command\\n\");\n\n\t\t} else if (buffer[0] == GOWAITWLAN_R) {\n\n\t\t\tCWDebugLog(\"Hostapd WTP in WAIT \\\"ADD WLAN\\\" Command\\n\");\n\t\t\tif( gWTPNextState == CW_ENTER_RUN) gWTPNextState = CW_ENTER_RESET;\n\n\t\t} else {\n\n\t\t\tCWDebugLog(\"Received Unknow Command from Hostapd WTP(%d)\", buffer[0]);\n\t\t}\n\n\t}\n\n\tclose(sock);\n\treturn (NULL);\n}\n"
  },
  {
    "path": "WTPipcHostapd.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Sotiraq Sima (Sotiraq.Sima@gmail.com)                                         *\n *                                                                                         *\n *******************************************************************************************/\n\n#ifndef __WTPipcHostapd_H\n#define __WTPipcHostapd_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include \"smac_code.h\"\n\n#include \"CWWTP.h\"\n\nvoid CWWTPsend_data_to_hostapd(unsigned char *buf, int len);\nvoid CWWTPsend_command_to_hostapd_SET_TXQ(unsigned char *buf, int len);\nvoid CWWTPsend_command_to_hostapd_SET_ADDR(unsigned char *buf, int len);\nvoid CWWTPsend_command_to_hostapd_ADD_WLAN(unsigned char *buf, int len);\nvoid CWWTPsend_command_to_hostapd_DEL_WLAN(unsigned char *buf, int len);\nvoid CWWTPsend_command_to_hostapd_DEL_ADDR(unsigned char *buf, int len);\nvoid CWWTPsend_command_to_hostapd_CLOSE(unsigned char *buf, int len);\nvoid CWWTP_get_WTP_MDC(unsigned char *buf);\nvoid CWWTP_get_WTP_Rates(unsigned char *buf);\nunsigned char CWTP_get_WTP_Radio_Information(void);\n\n#endif\n"
  },
  {
    "path": "WTPmacDriverInteraction.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n/*prototipi da includere in CWWTP.h*/\n#include \"CWWTP.h\"\n#include \"WTPipcHostapd.h\"\n\nint set_rts_threshold(int value);\nint get_rts_threshold(int *value);\n\nint set_frag_threshold(int value);\nint get_frag_threshold(int *value);\n\n/*--------------------------- RTS/CTS Threshold ---------------------------*/\nint set_rts_threshold(int value)\n{\n\n\tprintf(\"\\nRTS/CTS threshold impostato a: %d\\n\", value);\n\treturn 1;\n}\n\nint get_rts_threshold(int *value)\n{\n\n\tprintf(\"\\nRTS/CTS threshold: %d\\n\", *value);\n\treturn 1;\n}\n\n/*--------------------------- Fragmentation Threshold ---------------------------*/\nint set_frag_threshold(int value)\n{\n\n\tprintf(\"\\nFragmentation threshold impostato a: %d\\n\", value);\n\treturn 1;\n}\n\nint get_frag_threshold(int *value)\n{\n\n\tprintf(\"\\nFragmentation threshold: %d\\n\", *value);\n\treturn 1;\n}\n\nint set_txq(int code, int cwmin, int cwmax, int aifs, int burst_time)\n{\n\tchar str[32];\n\tsprintf(str, \"X%d %d %d %d %d\", code, cwmin, cwmax, aifs, burst_time);\n\n\tCWWTPsend_command_to_hostapd_SET_TXQ((unsigned char*)str, strlen(str));\n\treturn 1;\n}\n\n/*set CWMIN*/\nint set_wme_cwmin(int class, int value)\n{\n\n\tprintf(\"\\nCWMIN impostato a: %d\\n\", value);\n\treturn 1;\n}\n\n/*set CWMAX*/\nint set_wme_cwmax(int class, int value)\n{\n\n\tprintf(\"\\nCWMAX impostato a: %d\\n\", value);\n\treturn 1;\n}\n\n/*set AIFSN*/\nint set_wme_aifsn(int class, int value)\n{\n\n\tprintf(\"\\nAIFSN impostato a: %d\\n\", value);\n\treturn 1;\n}\n"
  },
  {
    "path": "WTPmacDriverInteraction.h",
    "content": "\n#define __CAPWAP_WTPBroadcomDriverInteraction_HEADER__\n\n/* check this magic number */\n#define WLC_IOCTL_MAGIC     0x14e46c77\n\n/* bump this number if you change the ioctl interface */\n#define WLC_IOCTL_VERSION   1\n\n#define WLC_IOCTL_MAXLEN    8192\t/* max length ioctl buffer required */\n#define WLC_IOCTL_SMLEN     256\t/* \"small\" length ioctl buffer required */\n\n/* common ioctl definitions */\n#define WLC_GET_MAGIC               0\n#define WLC_GET_VERSION             1\n#define WLC_UP                  2\n#define WLC_DOWN                3\n#define WLC_DUMP                6\n#define WLC_GET_MSGLEVEL            7\n#define WLC_SET_MSGLEVEL            8\n#define WLC_GET_PROMISC             9\n#define WLC_SET_PROMISC             10\n#define WLC_GET_RATE                12\n\t\t\t\t\t  /* #define WLC_SET_RATE             13 *//* no longer supported */\n#define WLC_GET_INSTANCE            14\n\t\t\t\t\t  /* #define WLC_GET_FRAG             15 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_FRAG             16 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_GET_RTS              17 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_RTS              18 *//* no longer supported */\n#define WLC_GET_INFRA               19\n#define WLC_SET_INFRA               20\n#define WLC_GET_AUTH                21\n#define WLC_SET_AUTH                22\n#define WLC_GET_BSSID               23\n#define WLC_SET_BSSID               24\n#define WLC_GET_SSID                25\n#define WLC_SET_SSID                26\n#define WLC_RESTART             27\n#define WLC_GET_CHANNEL             29\n#define WLC_SET_CHANNEL             30\n#define WLC_GET_SRL             31\n#define WLC_SET_SRL             32\n#define WLC_GET_LRL             33\n#define WLC_SET_LRL             34\n#define WLC_GET_PLCPHDR             35\n#define WLC_SET_PLCPHDR             36\n#define WLC_GET_RADIO               37\n#define WLC_SET_RADIO               38\n#define WLC_GET_PHYTYPE             39\n\t\t\t\t\t  /* #define WLC_GET_WEP              42 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_WEP              43 *//* no longer supported */\n#define WLC_GET_KEY             44\n#define WLC_SET_KEY             45\n#define WLC_GET_REGULATORY          46\n#define WLC_SET_REGULATORY          47\n#define WLC_GET_PASSIVE             48\n#define WLC_SET_PASSIVE             49\n#define WLC_SCAN                50\n#define WLC_SCAN_RESULTS            51\n#define WLC_DISASSOC                52\n#define WLC_REASSOC             53\n#define WLC_GET_ROAM_TRIGGER            54\n#define WLC_SET_ROAM_TRIGGER            55\n#define WLC_GET_TXANT               61\n#define WLC_SET_TXANT               62\n#define WLC_GET_ANTDIV              63\n#define WLC_SET_ANTDIV              64\n\t\t\t\t\t  /* #define WLC_GET_TXPWR            65 *//* no longer supported */\n\t\t\t\t\t  /* #define WLC_SET_TXPWR            66 *//* no longer supported */\n#define WLC_GET_CLOSED              67\n#define WLC_SET_CLOSED              68\n#define WLC_GET_MACLIST             69\n#define WLC_SET_MACLIST             70\n#define WLC_GET_RATESET             71\n#define WLC_SET_RATESET             72\n#define WLC_GET_LOCALE              73\n#define WLC_LONGTRAIN               74\n#define WLC_GET_BCNPRD              75\n#define WLC_SET_BCNPRD              76\n#define WLC_GET_DTIMPRD             77\n#define WLC_SET_DTIMPRD             78\n#define WLC_GET_SROM                79\n#define WLC_SET_SROM                80\n#define WLC_GET_WEP_RESTRICT            81\n#define WLC_SET_WEP_RESTRICT            82\n#define WLC_GET_COUNTRY             83\n#define WLC_SET_COUNTRY             84\n#define WLC_GET_PM              85\n#define WLC_SET_PM              86\n#define WLC_GET_WAKE                87\n#define WLC_SET_WAKE                88\n#define WLC_GET_D11CNTS             89\n#define WLC_GET_FORCELINK           90\t/* ndis only */\n#define WLC_SET_FORCELINK           91\t/* ndis only */\n#define WLC_FREQ_ACCURACY           92\n#define WLC_CARRIER_SUPPRESS            93\n#define WLC_GET_PHYREG              94\n#define WLC_SET_PHYREG              95\n#define WLC_GET_RADIOREG            96\n#define WLC_SET_RADIOREG            97\n#define WLC_GET_REVINFO             98\n#define WLC_GET_UCANTDIV            99\n#define WLC_SET_UCANTDIV            100\n#define WLC_R_REG               101\n#define WLC_W_REG               102\n#define WLC_DIAG_LOOPBACK           103\n#define WLC_RESET_D11CNTS           104\n#define WLC_GET_MACMODE             105\n#define WLC_SET_MACMODE             106\n#define WLC_GET_MONITOR             107\n#define WLC_SET_MONITOR             108\n#define WLC_GET_GMODE               109\n#define WLC_SET_GMODE               110\n#define WLC_GET_LEGACY_ERP          111\n#define WLC_SET_LEGACY_ERP          112\n#define WLC_GET_RX_ANT              113\n#define WLC_GET_CURR_RATESET            114\t/* current rateset */\n#define WLC_GET_SCANSUPPRESS            115\n#define WLC_SET_SCANSUPPRESS            116\n#define WLC_GET_AP              117\n#define WLC_SET_AP              118\n#define WLC_GET_EAP_RESTRICT            119\n#define WLC_SET_EAP_RESTRICT            120\n#define WLC_SCB_AUTHORIZE           121\n#define WLC_SCB_DEAUTHORIZE         122\n#define WLC_GET_WDSLIST             123\n#define WLC_SET_WDSLIST             124\n#define WLC_GET_ATIM                125\n#define WLC_SET_ATIM                126\n#define WLC_GET_RSSI                127\n#define WLC_GET_PHYANTDIV           128\n#define WLC_SET_PHYANTDIV           129\n#define WLC_AP_RX_ONLY              130\n#define WLC_GET_TX_PATH_PWR         131\n#define WLC_SET_TX_PATH_PWR         132\n#define WLC_GET_WSEC                133\n#define WLC_SET_WSEC                134\n#define WLC_GET_PHY_NOISE           135\n#define WLC_GET_BSS_INFO            136\n#define WLC_GET_PKTCNTS             137\n#define WLC_GET_LAZYWDS             138\n#define WLC_SET_LAZYWDS             139\n#define WLC_GET_BANDLIST            140\n#define WLC_GET_BAND                141\n#define WLC_SET_BAND                142\n#define WLC_SCB_DEAUTHENTICATE          143\n#define WLC_GET_SHORTSLOT           144\n#define WLC_GET_SHORTSLOT_OVERRIDE      145\n#define WLC_SET_SHORTSLOT_OVERRIDE      146\n#define WLC_GET_SHORTSLOT_RESTRICT      147\n#define WLC_SET_SHORTSLOT_RESTRICT      148\n#define WLC_GET_GMODE_PROTECTION        149\n#define WLC_GET_GMODE_PROTECTION_OVERRIDE   150\n#define WLC_SET_GMODE_PROTECTION_OVERRIDE   151\n#define WLC_UPGRADE             152\n\t\t\t\t\t   /* #define WLC_GET_MRATE            153 *//* no longer supported */\n\t\t\t\t\t   /* #define WLC_SET_MRATE            154 *//* no longer supported */\n#define WLC_GET_ASSOCLIST           159\n#define WLC_GET_CLK             160\n#define WLC_SET_CLK             161\n#define WLC_GET_UP              162\n#define WLC_OUT                 163\n#define WLC_GET_WPA_AUTH            164\n#define WLC_SET_WPA_AUTH            165\n#define WLC_GET_PROTECTION_CONTROL      178\n#define WLC_SET_PROTECTION_CONTROL      179\n#define WLC_GET_PHYLIST             180\n#define WLC_GET_KEY_SEQ             183\n\t\t\t\t\t\t   /* #define WLC_GET_GMODE_PROTECTION_CTS     198 *//* no longer supported */\n\t\t\t\t\t\t   /* #define WLC_SET_GMODE_PROTECTION_CTS     199 *//* no longer supported */\n#define WLC_GET_PIOMODE             203\n#define WLC_SET_PIOMODE             204\n#define WLC_SET_LED             209\n#define WLC_GET_LED             210\n#define WLC_GET_CHANNEL_SEL         215\n#define WLC_START_CHANNEL_SEL           216\n#define WLC_GET_VALID_CHANNELS          217\n#define WLC_GET_FAKEFRAG            218\n#define WLC_SET_FAKEFRAG            219\n#define WLC_GET_WET             230\n#define WLC_SET_WET             231\n#define WLC_GET_KEY_PRIMARY         235\n#define WLC_SET_KEY_PRIMARY         236\n#define WLC_GET_RADAR               242\n#define WLC_SET_RADAR               243\n#define WLC_SET_SPECT_MANAGMENT         244\n#define WLC_GET_SPECT_MANAGMENT         245\n#define WLC_WDS_GET_REMOTE_HWADDR       246\t/* handled in wl_linux.c/wl_vx.c */\n#define WLC_SET_CS_SCAN_TIMER           248\n#define WLC_GET_CS_SCAN_TIMER           249\n#define WLC_SEND_PWR_CONSTRAINT         254\n#define WLC_CURRENT_PWR             256\n#define WLC_GET_CHANNELS_IN_COUNTRY     260\n#define WLC_GET_COUNTRY_LIST            261\n#define WLC_GET_VAR             262\t/* get value of named variable */\n#define WLC_SET_VAR             263\t/* set named variable to value */\n#define WLC_NVRAM_GET               264\t/* deprecated */\n#define WLC_NVRAM_SET               265\n#define WLC_SET_WSEC_PMK            268\n#define WLC_GET_AUTH_MODE           269\n#define WLC_SET_AUTH_MODE           270\n#define WLC_NDCONFIG_ITEM           273\t/* currently handled in wl_oid.c */\n#define WLC_NVOTPW              274\n#define WLC_OTPW                275\n#define WLC_SET_LOCALE              278\n#define WLC_LAST                279\t/* do not change - use get_var/set_var */\n\n/* ** driver/apps-shared section ** */\n\n#define BCME_STRLEN         64\t/* Max string length for BCM errors */\n#define VALID_BCMERROR(e)  ((e <= 0) && (e >= BCME_LAST))\n\n/*\n * error codes could be added but the defined ones shouldn't be changed/deleted\n * these error codes are exposed to the user code\n * when ever a new error code is added to this list\n * please update errorstring table with the related error string and\n * update osl files with os specific errorcode map\n*/\n\n#define BCME_OK             0\t/* Success */\n#define BCME_ERROR          -1\t/* Error generic */\n#define BCME_BADARG         -2\t/* Bad Argument */\n#define BCME_BADOPTION          -3\t/* Bad option */\n#define BCME_NOTUP          -4\t/* Not up */\n#define BCME_NOTDOWN            -5\t/* Not down */\n#define BCME_NOTAP          -6\t/* Not AP */\n#define BCME_NOTSTA         -7\t/* Not STA  */\n#define BCME_BADKEYIDX          -8\t/* BAD Key Index */\n#define BCME_RADIOOFF           -9\t/* Radio Off */\n#define BCME_NOTBANDLOCKED      -10\t/* Not  band locked */\n#define BCME_NOCLK          -11\t/* No Clock */\n#define BCME_BADRATESET         -12\t/* BAD Rate valueset */\n#define BCME_BADBAND            -13\t/* BAD Band */\n#define BCME_BUFTOOSHORT        -14\t/* Buffer too short */\n#define BCME_BUFTOOLONG         -15\t/* Buffer too long */\n#define BCME_BUSY           -16\t/* Busy */\n#define BCME_NOTASSOCIATED      -17\t/* Not Associated */\n#define BCME_BADSSIDLEN         -18\t/* Bad SSID len */\n#define BCME_OUTOFRANGECHAN     -19\t/* Out of Range Channel */\n#define BCME_BADCHAN            -20\t/* Bad Channel */\n#define BCME_BADADDR            -21\t/* Bad Address */\n#define BCME_NORESOURCE         -22\t/* Not Enough Resources */\n#define BCME_UNSUPPORTED        -23\t/* Unsupported */\n#define BCME_BADLEN         -24\t/* Bad length */\n#define BCME_NOTREADY           -25\t/* Not Ready */\n#define BCME_EPERM          -26\t/* Not Permitted */\n#define BCME_NOMEM          -27\t/* No Memory */\n#define BCME_ASSOCIATED         -28\t/* Associated */\n#define BCME_RANGE          -29\t/* Not In Range */\n#define BCME_NOTFOUND           -30\t/* Not Found */\n#define BCME_WME_NOT_ENABLED        -31\t/* WME Not Enabled */\n#define BCME_TSPEC_NOTFOUND     -32\t/* TSPEC Not Found */\n#define BCME_ACM_NOTSUPPORTED       -33\t/* ACM Not Supported */\n#define BCME_NOT_WME_ASSOCIATION    -34\t/* Not WME Association */\n#define BCME_SDIO_ERROR         -35\t/* SDIO Bus Error */\n#define BCME_DONGLE_DOWN        -36\t/* Dongle Not Accessible */\n#define BCME_LAST           BCME_DONGLE_DOWN\n\n/* These are collection of BCME Error strings */\n#define BCMERRSTRINGTABLE {     \\\n    \"OK\",               \\\n    \"Undefined error\",      \\\n    \"Bad Argument\",         \\\n    \"Bad Option\",           \\\n    \"Not up\",           \\\n    \"Not down\",         \\\n    \"Not AP\",           \\\n    \"Not STA\",          \\\n    \"Bad Key Index\",        \\\n    \"Radio Off\",            \\\n    \"Not band locked\",      \\\n    \"No clock\",         \\\n    \"Bad Rate valueset\",        \\\n    \"Bad Band\",         \\\n    \"Buffer too short\",     \\\n    \"Buffer too long\",      \\\n    \"Busy\",             \\\n    \"Not Associated\",       \\\n    \"Bad SSID len\",         \\\n    \"Out of Range Channel\",     \\\n    \"Bad Channel\",          \\\n    \"Bad Address\",          \\\n    \"Not Enough Resources\",     \\\n    \"Unsupported\",          \\\n    \"Bad length\",           \\\n    \"Not Ready\",            \\\n    \"Not Permitted\",        \\\n    \"No Memory\",            \\\n    \"Associated\",           \\\n    \"Not In Range\",         \\\n    \"Not Found\",            \\\n    \"WME Not Enabled\",      \\\n    \"TSPEC Not Found\",      \\\n    \"ACM Not Supported\",        \\\n    \"Not WME Association\",      \\\n    \"SDIO Bus Error\",       \\\n    \"Dongle Not Accessible\"     \\\n}\n\n/* Types definition*/\n/*\n * Inferred Typedefs\n *\n */\n\n/* Infer the compile environment based on preprocessor symbols and pramas.\n * Override type definitions as needed, and include configuration dependent\n * header files to define types.\n */\n\n#ifdef __cplusplus\n\n#define TYPEDEF_BOOL\n#ifndef FALSE\n#define FALSE   false\n#endif\n#ifndef TRUE\n#define TRUE    true\n#endif\n\n#endif\t\t\t\t/* __cplusplus */\n\n#if defined(_NEED_SIZE_T_)\ntypedef long unsigned int size_t;\n#endif\n\n#define TYPEDEF_UINT\n#define TYPEDEF_USHORT\n#define TYPEDEF_ULONG\n\n/* Do not support the (u)int64 types with strict ansi for GNU C */\n#if defined(__GNUC__) && defined(__STRICT_ANSI__)\n#define TYPEDEF_INT64\n#define TYPEDEF_UINT64\n#endif\n\n/* pick up ushort & uint from standard types.h */\n#if defined(linux) && defined(__KERNEL__)\n#include <linux/types.h>\t/* sys/types.h and linux/types.h are oil and water */\n#else\n#include <sys/types.h>\n#endif\n\n/* use the default typedefs in the next section of this file */\n#define USE_TYPEDEF_DEFAULTS\n\n/*\n * Default Typedefs\n *\n */\n\n#ifdef USE_TYPEDEF_DEFAULTS\n#undef USE_TYPEDEF_DEFAULTS\n\n#ifndef TYPEDEF_BOOL\ntypedef /* @abstract@ */ unsigned char bool;\n#endif\n\n/* define uchar, ushort, uint, ulong */\n\n#ifndef TYPEDEF_UCHAR\ntypedef unsigned char uchar;\n#endif\n\n#ifndef TYPEDEF_USHORT\ntypedef unsigned short ushort;\n#endif\n\n#ifndef TYPEDEF_UINT\ntypedef unsigned int uint;\n#endif\n\n#ifndef TYPEDEF_ULONG\ntypedef unsigned long ulong;\n#endif\n\n/* define [u]int8/16/32/64, uintptr */\n\n#ifndef TYPEDEF_UINT8\ntypedef unsigned char uint8;\n#endif\n\n#ifndef TYPEDEF_UINT16\ntypedef unsigned short uint16;\n#endif\n\n#ifndef TYPEDEF_UINT32\ntypedef unsigned int uint32;\n#endif\n\n#ifndef TYPEDEF_UINT64\ntypedef unsigned long long uint64;\n#endif\n\n#ifndef TYPEDEF_UINTPTR\ntypedef unsigned int uintptr;\n#endif\n\n#ifndef TYPEDEF_INT8\ntypedef signed char int8;\n#endif\n\n#ifndef TYPEDEF_INT16\ntypedef signed short int16;\n#endif\n\n#ifndef TYPEDEF_INT32\ntypedef signed int int32;\n#endif\n\n#ifndef TYPEDEF_INT64\ntypedef signed long long int64;\n#endif\n\n/* define float32/64, float_t */\n\n#ifndef TYPEDEF_FLOAT32\ntypedef float float32;\n#endif\n\n#ifndef TYPEDEF_FLOAT64\ntypedef double float64;\n#endif\n\n/*\n * abstracted floating point type allows for compile time selection of\n * single or double precision arithmetic.  Compiling with -DFLOAT32\n * selects single precision; the default is double precision.\n */\n\n#ifndef TYPEDEF_FLOAT_T\n\n#if defined(FLOAT32)\ntypedef float32 float_t;\n#else\t\t\t\t/* default to double precision floating point */\ntypedef float64 float_t;\n#endif\n\n#endif\t\t\t\t/* TYPEDEF_FLOAT_T */\n\n/* define macro values */\n\n#ifndef FALSE\n#define FALSE   0\n#endif\n\n#ifndef TRUE\n#define TRUE    1\t\t/* TRUE */\n#endif\n\n#ifndef NULL\n#define NULL    0\n#endif\n\n#ifndef OFF\n#define OFF 0\n#endif\n\n#ifndef ON\n#define ON  1\t\t\t/* ON = 1 */\n#endif\n\n#define AUTO    (-1)\t\t/* Auto = -1 */\n\n/* define PTRSZ, INLINE */\n\n#ifndef PTRSZ\n#define PTRSZ   sizeof(char*)\n#endif\n\n#ifndef INLINE\n\n#ifdef _MSC_VER\n\n#define INLINE __inline\n\n#elif __GNUC__\n\n#define INLINE __inline__\n\n#else\n\n#define INLINE\n\n#endif\t\t\t\t/* _MSC_VER */\n\n#endif\t\t\t\t/* INLINE */\n\n#undef TYPEDEF_BOOL\n#undef TYPEDEF_UCHAR\n#undef TYPEDEF_USHORT\n#undef TYPEDEF_UINT\n#undef TYPEDEF_ULONG\n#undef TYPEDEF_UINT8\n#undef TYPEDEF_UINT16\n#undef TYPEDEF_UINT32\n#undef TYPEDEF_UINT64\n#undef TYPEDEF_UINTPTR\n#undef TYPEDEF_INT8\n#undef TYPEDEF_INT16\n#undef TYPEDEF_INT32\n#undef TYPEDEF_INT64\n#undef TYPEDEF_FLOAT32\n#undef TYPEDEF_FLOAT64\n#undef TYPEDEF_FLOAT_T\n\n/* WME Access Category Indices (ACIs) */\n#define AC_BE           0\t/* Best Effort */\n#define AC_BK           1\t/* Background */\n#define AC_VI           2\t/* Video */\n#define AC_VO           3\t/* Voice */\n#define AC_COUNT        4\t/* number of ACs */\n\nstruct edcf_acparam {\n\tuint8 ACI;\n\tuint8 ECW;\n\tuint16 TXOP;\t\t/* stored in network order (ls octet first) */\n} PACKED;\ntypedef struct edcf_acparam edcf_acparam_t;\n\n/* Linux network driver ioctl encoding */\ntypedef struct wl_ioctl {\n\tuint cmd;\t\t/* common ioctl definition */\n\tvoid *buf;\t\t/* pointer to user buffer */\n\tuint len;\t\t/* length of user buffer */\n\tbool set;\t\t/* get or set request (optional) */\n\tuint used;\t\t/* bytes read or written (optional) */\n\tuint needed;\t\t/* bytes needed (optional) */\n} wl_ioctl_t;\n\n/*\n * Pass a wlioctl request to the specified interface.\n * @param   name    interface name\n * @param   cmd WLC_GET_MAGIC <= cmd < WLC_LAST\n * @param   buf buffer for passing in and/or receiving data\n * @param   len length of buf\n * @return  >= 0 if successful or < 0 otherwise\n */\nextern int wl_ioctl(char *name, int cmd, void *buf, int len);\n\nextern int wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen);\nextern int wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen);\n/*\n * Set/Get named variable.\n * @param   ifname      interface name\n * @param   iovar       variable name\n * @param   param       input param value/buffer\n * @param   paramlen    input param value/buffer length\n * @param   bufptr      io buffer\n * @param   buflen      io buffer length\n * @param   val     val or val pointer for int routines\n * @return  success == 0, failure != 0\n */\n/*\n * set named driver variable to int value\n * calling example: wl_iovar_setint(ifname, \"arate\", rate)\n*/\nstatic inline int wl_iovar_setint(char *ifname, char *iovar, int val)\n{\n\treturn wl_iovar_set(ifname, iovar, &val, sizeof(val));\n}\n\n/*\n * get named driver variable to int value and return error indication\n * calling example: wl_iovar_getint(ifname, \"arate\", &rate)\n */\nstatic inline int wl_iovar_getint(char *ifname, char *iovar, int *val)\n{\n\treturn wl_iovar_get(ifname, iovar, val, sizeof(int));\n}\n\n#endif\n"
  },
  {
    "path": "WTPmacFrameReceive.c",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#include \"WTPmacFrameReceive.h\"\n#include \"common.h\"\n#include \"ieee802_11_defs.h\"\n\n#define TYPE_LEN 2\n#define ETH_ALEN 6\n#define ETH_HLEN 14\n#define FRAME_80211_LEN 24\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\n#define EXIT_FRAME_THREAD(sock) CWLog(\"ERROR Handling Frames: application will be closed!\");        \\\n                close(sock);                                \\\n                exit(1);\n\nint getMacAddr(int sock, char *interface, unsigned char *macAddr)\n{\n\n\tstruct ifreq s;\n\tint fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);\n\tstrcpy(s.ifr_name, interface);\n\tif (!ioctl(fd, SIOCGIFHWADDR, &s))\n\t\tmemcpy(macAddr, s.ifr_addr.sa_data, MAC_ADDR_LEN);\n\n\tCWDebugLog(\"\\n\");\n\n\treturn 1;\n}\n\nint extractFrameInfo(char *buffer, char *RSSI, char *SNR, int *dataRate)\n{\n\tint signal, noise;\n\n\t*RSSI = buffer[RSSI_BYTE] - ATHEROS_CONV_VALUE;\t//RSSI in dBm\n\n\tsignal = buffer[SIGNAL_BYTE] - ATHEROS_CONV_VALUE;\n\tnoise = buffer[NOISE_BYTE];\n\t*SNR = (char)signal - noise;\t//RSN in dB\n\n\t*dataRate = (buffer[DATARATE_BYTE] / 2) * 10;\t//Data rate in Mbps*10\n\treturn 1;\n}\n\nint extractFrame(CWProtocolMessage ** frame, unsigned char *buffer, int len)\n{\n\n\tCW_CREATE_OBJECT_ERR(*frame, CWProtocolMessage, return 0;\n\t    );\n\tCWProtocolMessage *auxPtr = *frame;\n\tCW_CREATE_PROTOCOL_MESSAGE(*auxPtr, len - PRISMH_LEN, return 0;\n\t    );\n\tmemcpy(auxPtr->msg, buffer + PRISMH_LEN, len - PRISMH_LEN);\n\tauxPtr->offset = len - PRISMH_LEN;\n\treturn 1;\n}\n\nint extract802_11_Frame(CWProtocolMessage ** frame, unsigned char *buffer, int len)\n{\n\tCW_CREATE_OBJECT_ERR(*frame, CWProtocolMessage, return 0;\n\t    );\n\tCWProtocolMessage *auxPtr = *frame;\n\tCW_CREATE_PROTOCOL_MESSAGE(*auxPtr, len, return 0;\n\t    );\n\tmemcpy(auxPtr->msg, buffer, len);\n\tauxPtr->offset = len;\n\treturn 1;\n}\n\nint extractAddr(unsigned char *destAddr, unsigned char *sourceAddr, char *frame)\n{\n\tmemset(destAddr, 0, MAC_ADDR_LEN);\n\tmemset(sourceAddr, 0, MAC_ADDR_LEN);\n\tmemcpy(destAddr, frame + DEST_ADDR_START, MAC_ADDR_LEN);\n\tmemcpy(sourceAddr, frame + SOURCE_ADDR_START, MAC_ADDR_LEN);\n\n\treturn 1;\n}\n\nint macAddrCmp(unsigned char *addr1, unsigned char *addr2)\n{\n\tint i, ok = 1;\n\n\tfor (i = 0; i < MAC_ADDR_LEN; i++) {\n\t\tif (addr1[i] != addr2[i]) {\n\t\t\tok = 0;\n\t\t}\n\t}\n\n\tif (ok == 1) {\n\t\tCWDebugLog(\"MAC Address test: OK\\n\");\n\t} else {\n\t\tCWDebugLog(\"MAC Address test: Failed\\n\");\n\t}\n\n\treturn ok;\n}\n\nint from_8023_to_80211(unsigned char *inbuffer, int inlen, unsigned char *outbuffer, unsigned char *own_addr)\n{\n\n\tint indx = 0;\n\tstruct ieee80211_hdr hdr;\n\tos_memset(&hdr, 0, sizeof(struct ieee80211_hdr));\n\n\thdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA) | host_to_le16(WLAN_FC_TODS);\n\thdr.duration_id = 0;\n\thdr.seq_ctrl = 0;\n\n\tos_memcpy(hdr.addr1, own_addr, ETH_ALEN);\n\tos_memcpy(hdr.addr2, inbuffer + ETH_ALEN, ETH_ALEN);\n\tos_memcpy(hdr.addr3, inbuffer, ETH_ALEN);\n\n\tos_memcpy(outbuffer + indx, &hdr, sizeof(hdr));\n\tindx += sizeof(hdr);\n\tos_memcpy(outbuffer + indx, inbuffer, inlen);\n\tindx += inlen;\n\n\treturn indx;\n}\n\nint gRawSock;\nextern int wtpInRunState;\n\nint CWWTPSendFrame(unsigned char *buf, int len)\n{\n\n\tif (send(gRawSock, buf + FRAME_80211_LEN, len - FRAME_80211_LEN, 0) < 1) {\n\t\tCWDebugLog(\"Error to send frame on raw socket\");\n\t\treturn -1;\n\t}\n\tCWDebugLog(\"Send (%d) bytes on raw socket\", len - FRAME_80211_LEN);\n\n\treturn 1;\n\n}\n\nCW_THREAD_RETURN_TYPE CWWTPReceiveFrame(void *arg)\n{\n\n\tint n, encaps_len;\n\tunsigned char buffer[CW_BUFFER_SIZE];\n\tunsigned char buf80211[CW_BUFFER_SIZE];\n\tunsigned char macAddr[MAC_ADDR_LEN];\n\n\tstruct sockaddr_ll addr;\n\n\tCWBindingDataListElement *listElement = NULL;\n\tstruct ifreq ethreq;\n\n\tCWThreadSetSignals(SIG_BLOCK, 1, SIGALRM);\n\n\tif ((gRawSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {\n\t\tCWDebugLog(\"THR FRAME: Error creating socket\");\n\t\tCWExitThread();\n\t}\n\tmemset(&addr, 0, sizeof(addr));\n\n\taddr.sll_family = AF_PACKET;\n\taddr.sll_protocol = htons(ETH_P_ALL);\n\taddr.sll_pkttype = PACKET_HOST;\n\taddr.sll_ifindex = if_nametoindex(gRadioInterfaceName_0);\n\n\tif ((bind(gRawSock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {\n\t\tCWDebugLog(\"THR FRAME: Error binding socket\");\n\t\tCWExitThread();\n\t}\n\n\tif (!getMacAddr(gRawSock, gRadioInterfaceName_0, macAddr)) {\n\t\tCWDebugLog(\"THR FRAME: Ioctl error\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n\n\t/* Set the network card in promiscuos mode */\n\tstrncpy(ethreq.ifr_name, gRadioInterfaceName_0, IFNAMSIZ);\n\tif (ioctl(gRawSock, SIOCGIFFLAGS, &ethreq) == -1) {\n\t\tCWDebugLog(\"THR FRAME: Error ioctl\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n\tethreq.ifr_flags |= IFF_PROMISC;\n\tif (ioctl(gRawSock, SIOCSIFFLAGS, &ethreq) == -1) {\n\t\tCWDebugLog(\"THR FRAME: Error ioctl\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n\n#ifdef FILTER_ON\n\t/* Attach the filter to the socket */\n\tif (setsockopt(gRawSock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)) < 0) {\n\t\tCWDebugLog(\"THR FRAME: Error attaching filter\");\n\t\tEXIT_FRAME_THREAD(gRawSock);\n\t}\n#endif\n\n\tCW_REPEAT_FOREVER {\n\n\t\tn = recvfrom(gRawSock, buffer, sizeof(buffer), 0, NULL, NULL);\n\n\t\tif (n < 0)\n\t\t\tcontinue;\n\t \t//disabling data tunnel\t\n\t\tcontinue;\n\n\t\tif (!wtpInRunState) {\n\t\t\tCWLog(\"macframe packet - WTP is not in RUN state\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tCW_CREATE_OBJECT_ERR(listElement, CWBindingDataListElement, EXIT_FRAME_THREAD(gRawSock);\n\t\t    );\n\n\t\tif (gWTPTunnelMode == CW_TUNNEL_MODE_802_DOT_11_TUNNEL) {\n\t\t\tencaps_len = from_8023_to_80211(buffer, n, buf80211, macAddr);\n\n\t\t\tif (!extract802_11_Frame(&listElement->frame, buf80211, encaps_len)) {\n\t\t\t\tCWDebugLog(\"THR FRAME: Error extracting a frame\");\n\t\t\t\tEXIT_FRAME_THREAD(gRawSock);\n\t\t\t}\n\n\t\t\tlistElement->frame->data_msgType = CW_IEEE_802_11_FRAME_TYPE;\n\n\t\t\tCWDebugLog(\"Recv 802.11 data(len:%d) from %s\", encaps_len, gRadioInterfaceName_0);\n\t\t\n\t\t} else {\n\t\t\tif (!extract802_11_Frame(&listElement->frame, buffer, n)) {\n\t\t\t\tCWDebugLog(\"THR FRAME: Error extracting a frame\");\n\t\t\t\tEXIT_FRAME_THREAD(gRawSock);\n\t\t\t}\n\n\t\t\tlistElement->frame->data_msgType = CW_IEEE_802_3_FRAME_TYPE;\n\n\t\t\tCWDebugLog(\"Recv 802.3 data(len:%d) from %s\", n, gRadioInterfaceName_0);\n\t\t}\n\n\t\tlistElement->bindingValues = NULL;\n\n\t\tCWLockSafeList(gFrameList);\n\t\tCWAddElementToSafeListTail(gFrameList, listElement, sizeof(CWBindingDataListElement));\n\t\tCWUnlockSafeList(gFrameList);\n\t}\n\n\tclose(gRawSock);\n\treturn (NULL);\n}\n"
  },
  {
    "path": "WTPmacFrameReceive.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __CAPWAP_WTPFrameReceive_HEADER__\n#define __CAPWAP_WTPFrameReceive_HEADER__\n\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <linux/if_ether.h>\n#include <net/if.h>\n#include <sys/ioctl.h>\n#include <netpacket/packet.h>\n\n#include \"CWWTP.h\"\n\n#ifndef B_ENDIAN\n#define CHECK_PRISM_HEADER  (buffer[0]==MESSAGE_CODE_1) && \\\n                (buffer[1]==MESSAGE_CODE_2) && \\\n                (buffer[2]==MESSAGE_CODE_3) && \\\n                (buffer[3]==MESSAGE_CODE_4)\n#else\n#define CHECK_PRISM_HEADER  (buffer[3]==MESSAGE_CODE_1) && \\\n                (buffer[2]==MESSAGE_CODE_2) && \\\n                (buffer[1]==MESSAGE_CODE_3) && \\\n                (buffer[0]==MESSAGE_CODE_4)\n#endif\n\n//#define PROMODE_ON\n//#define FILTER_ON\n#define PRISMH_LEN      144\n#define RSSI_BYTE       68\n#define SIGNAL_BYTE     92\n#define NOISE_BYTE      104\n#define DATARATE_BYTE       116\n#define DEST_ADDR_START     4\n#define SOURCE_ADDR_START   10\n#define MESSAGE_CODE_1      68\n#define MESSAGE_CODE_2      0\n#define MESSAGE_CODE_3      0\n#define MESSAGE_CODE_4      0\n#define MAC_ADDR_LEN        6\n#define ATHEROS_CONV_VALUE  95\n\n#define ASSOCIATION_REQUEST_SUBTYPE 0\n#define ASSOCIATION_RESPONSE_SUBTYPE    1\n#define REASSOCIATION_REQUEST_SUBTYPE   2\n#define REASSOCIATION_RESPONSE_SUBTYPE  3\n#define PROBE_REQUEST_SUBTYPE       4\n#define PROBE_RESPONSE_SUBTYPE      5\n#define RESERVED6_SUBTYPE       6\n#define RESERVED7_SUBTYPE       7\n#define BEACON_SUBTYPE          8\n#define ATIM_SUBTYPE            9\n#define DISASSOCIATION_SUBTYPE      10\n#define AUTHENTICATION_SUBTYPE      11\n#define DEAUTHENTICATION_SUBTYPE    12\n\n#define RESERVED0_SUBTYPE       0\n#define RESERVED9_SUBTYPE       9\n#define POWER_SAVE_SUBTYPE      10\n#define RTS_SUBTYPE         11\n#define CTS_SUBTYPE         12\n#define ACKNOLEDGEMENT_SUBTYPE      13\n#define CF_END_SUBTYPE          14\n#define CF_END_CF_ACK_SUBTYPE       15\n\n#define DATA_SUBTYPE            0\n#define DATA_CF_ACK_SUBTYPE     1\n#define DATA_CF_POLL_SUBTYPE        2\n#define DATA_CF_ACK_CF_POLL_SUBTYPE 3\n#define NO_DATA_SUBTYPE         4\n#define CF_ACK_SUBTYPE          5\n#define CF_POLL_SUBTYPE         6\n#define CF_ACK_CF_POLL_SUBTYPE      7\n#define RESERVED8_SUBTYPE       8\n#define RESERVED15_SUBTYPE      15\n\nint extract802_11_Frame(CWProtocolMessage ** frame, unsigned char *buffer, int len);\nint CWWTPSendFrame(unsigned char *buf, int len);\n\n#endif\n"
  },
  {
    "path": "WUA.c",
    "content": "\n/*******************************************************************************************\n * Copyright (c) 2008 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author: Donato Capitella (d.capitella@gmail.com)                                        *\n *                                                                                         *\n *******************************************************************************************/\n\n#include <unistd.h>\n#include <wait.h>\n#include <sys/stat.h>\n#include <ctype.h>\n#include <time.h>\n#include \"CWCommon.h\"\n#include \"WUM.h\"\n\n/* WUA Constants */\n#define BUF_SIZE        1024\n#define CUP_UNPACK_DIR  \"/tmp/cup.unpack\"\n#define BACKUP_DIR      \"/tmp/cup.backup\"\n#define CUD_FILE_NAME   \"update.cud\"\n#define LOG_FILE        \"/var/log/wua.log\"\n\n#define WTP_DIR_VAR     \"WTP_DIR\"\n#define CUP_DIR_VAR     \"CUP_DIR\"\n\n/* Execute the system() function\n * and return CW_FALSE in case of failure. */\n#define SYSTEM_ERR(cmd) \\\ndo {  \\\n    int exit_c = system(cmd);  \\\n    if (!WIFEXITED(exit_c) || WEXITSTATUS(exit_c) != 0 ) { \\\n       return CW_FALSE; \\\n    } \\\n} while(0)\n\n/* CUPWAP Update Descriptor */\nstruct CWUpdateDescriptor {\n\tchar version[BUF_SIZE];\n\tchar pre_script[BUF_SIZE];\n\tchar post_script[BUF_SIZE];\n};\n\n/* Default values for CUD */\nstruct CWUpdateDescriptor cud = {\n\t.version[0] = '\\0',\n\t.pre_script[0] = '\\0',\n\t.post_script[0] = '\\0',\n};\n\n/* Function prototypes */\nCWBool Unzip(char *filename, char *destdir);\nCWBool MakeDir(char *dirname);\nCWBool BackupCurrentWTP(char *WTPDir);\nCWBool CheckCUPIntegrity();\nCWBool ParseCUD();\n\nCWBool StartWTP(char *WTPDir);\nvoid CleanTmpFiles(char *);\nCWBool RestoreBackupWTP(char *WTPDir);\n\nCWBool WUAStage1(char *CupPath, char *WTPDir);\nCWBool WUAStage2();\n\nvoid WaitForWTPTermination();\nvoid daemonize();\n\n/* Log related varibales and functions */\nFILE *log_file = NULL;\nCWBool WUAInitLog(char *logFile);\nvoid WUALog(char *msg, ...);\nvoid WUALogClose();\n\nint main(int argc, char *argv[])\n{\n\tif (argc < 2) {\n\t\tfprintf(stderr, \"Usage: %s cup_file\\n\", argv[0]);\n\t}\n\n\tdaemonize();\n\n\tWTPUpdateAgent(argv[1]);\n\treturn 0;\n}\n\n/*\n * WTPUpdateAgent - main routine of the WUA\n *\n * CupPath: pathname of the capwap update package\n *\n * This function executes an update session, which is divided\n * into three stages:\n *\n *   - Stage 1: preparation for the update (unpack CUP and\n *     backup current WTP)\n *\n *   - Stage 2: executes pre-update script, copies new files,\n *     then executes post-update script\n *\n *   - Final Stage: cleans temp files and start new WTP\n */\nvoid WTPUpdateAgent(char *CupPath)\n{\n\tint exit_status = EXIT_SUCCESS;\n\tchar WTPDir[BUF_SIZE];\n\n\tif (!WUAInitLog(LOG_FILE)) {\n\t\tgoto quit_wua;\n\t}\n\n\tWaitForWTPTermination();\n\n\tWUALog(\"Update Session Started.\");\n\n\tif (!getcwd(WTPDir, BUF_SIZE)) {\n\t\tWUALog(\"The impossible happened: can't get current working directory!\");\n\t\texit_status = EXIT_FAILURE;\n\t\tgoto quit_wua;\n\t}\n\n\tif (!WUAStage1(CupPath, WTPDir)) {\n\t\texit_status = EXIT_FAILURE;\n\t\tgoto quit_wua;\n\t}\n\n\tif (!WUAStage2(WTPDir)) {\n\t\texit_status = EXIT_FAILURE;\n\t\tif (!RestoreBackupWTP(WTPDir)) {\n\t\t\tWUALog(\"***CRITICAL ERROR*** -> Can't restore backup WTP!!!\");\n\t\t\texit(EXIT_FAILURE);\n\t\t}\n\t\tgoto quit_wua;\n\t}\n\n\t/* Final Stage */\n quit_wua:\n\tCleanTmpFiles(CupPath);\n\tStartWTP(WTPDir);\n\tWUALog(\"Update Session Ended %s\", (exit_status == EXIT_SUCCESS) ? \"Successefully\" : \"With Errors\");\n\tWUALogClose();\n\texit(exit_status);\n}\n\n/*\n * WaitForWTPTermination\n * This function returns when the WTP terminates. A lock on a file\n * is used for synchronization purposes.\n */\nvoid WaitForWTPTermination()\n{\n\tstruct flock fl;\n\tint fd;\n\n\t/* The following lock in set just for synchronization purposes */\n\tfl.l_type = F_WRLCK;\n\tfl.l_whence = SEEK_SET;\n\tfl.l_start = 0;\n\tfl.l_len = 0;\n\tfl.l_pid = getpid();\n\n\tif ((fd = open(WTP_LOCK_FILE, O_WRONLY)) < 0) {\n\t\tWUALog(\"Error while opening lock file: %s\\n\", WTP_LOCK_FILE);\n\t}\n\n\tfcntl(fd, F_SETLKW, &fl);\n\n\tclose(fd);\n\tremove(WTP_LOCK_FILE);\n\n\treturn;\n}\n\n/*\n * State 1 of the update process\n *\n * - Unpack & Check CUP file\n * - Backup current WTP\n */\nCWBool WUAStage1(char *CupPath, char *WTPDir)\n{\n\tWUALog(\"Entering Stage 1...\");\n\n\tif (!MakeDir(CUP_UNPACK_DIR)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!Unzip(CupPath, CUP_UNPACK_DIR)) {\n\t\tWUALog(\"Something wrong happened while unzipping the CUP archive.\");\n\t\treturn CW_FALSE;\n\t}\n\t/*\n\t   if (!CheckCUPIntegrity()) {\n\t   WUALog(\"Problems with the CUP archive.\");\n\t   return CW_FALSE;\n\t   }\n\t */\n\tif (!ParseCUD()) {\n\t\tWUALog(\"Error while parsing CUD.\");\n\t\treturn CW_FALSE;\n\t}\n\n\tWUALog(\"Update Version: %s\", cud.version);\n\n\tif (!MakeDir(BACKUP_DIR)) {\n\t\treturn CW_FALSE;\n\t}\n\n\tif (!BackupCurrentWTP(WTPDir)) {\n\t\tWUALog(\"Can't backup current WTP.\");\n\t\treturn CW_FALSE;\n\t}\n\n\tWUALog(\"Stage 1 completed successfully...\");\n\n\treturn CW_TRUE;\n}\n\n/*\n * State 2 of the update process\n *\n * - Set scripts variables\n * - Execute preupdate script\n * - Copy new files\n * - Execute postupdate script\n */\nCWBool WUAStage2(char *WTPDir)\n{\n\tint ret;\n\tchar cmd_buf[BUF_SIZE];\n\n\tWUALog(\"Entering Stage 2...\");\n\n\t/* Prepare env variables for the scripts */\n\tret = setenv(WTP_DIR_VAR, WTPDir, 1);\n\tif (ret != 0) {\n\t\tWUALog(\"Error while setting env variable.\");\n\t\treturn CW_FALSE;\n\t}\n\n\tret = setenv(CUP_DIR_VAR, CUP_UNPACK_DIR, 1);\n\tif (ret != 0) {\n\t\tWUALog(\"Error while setting env variable.\");\n\t\treturn CW_FALSE;\n\t}\n\n\t/* Execute pre-update script, if any */\n\tif (strlen(cud.pre_script) > 0) {\n\t\tSYSTEM_ERR(cud.pre_script);\n\t}\n\n\t/* Copy new WTP files */\n\tret = snprintf(cmd_buf, BUF_SIZE, \"cp -r %s/WTP/* %s/\", CUP_UNPACK_DIR, WTPDir);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn CW_FALSE;\n\t}\n\tSYSTEM_ERR(cmd_buf);\n\n\t/* Execute post-upsate script, if any */\n\tif (strlen(cud.post_script) > 0) {\n\t\tSYSTEM_ERR(cud.post_script);\n\t}\n\n\tWUALog(\"Stage 2 completed successefully.\");\n\treturn CW_TRUE;\n}\n\n/*\n * Unzip - unzips a gzipped archive into the provided directory.\n *\n * Notes: this implementation relies on the tar command.\n */\nCWBool Unzip(char *filename, char *destdir)\n{\n\tchar cmd_buf[BUF_SIZE];\n\tint ret;\n\n\tret = snprintf(cmd_buf, BUF_SIZE, \"tar xzf %s -C %s\", filename, destdir);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn CW_FALSE;\n\t}\n\n\tSYSTEM_ERR(cmd_buf);\n\n\treturn CW_TRUE;\n}\n\n/*\n * StartWTP - starts a WTP daemon\n *\n * WTPDir: the directory where the WTP binary resides.\n */\nCWBool StartWTP(char *WTPDir)\n{\n\tchar cmd_buf[BUF_SIZE];\n\tint pid, ret;\n\n\tret = snprintf(cmd_buf, BUF_SIZE, \"%s/WTP\", WTPDir);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn CW_FALSE;\n\t}\n\n\tpid = fork();\n\n\tif (pid == 0) {\n\t\texecl(cmd_buf, \"WTP\", WTPDir, NULL);\n\t\texit(EXIT_FAILURE);\n\t} else if (pid < 0) {\n\t\tWUALog(\"Error while forking\");\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\nCWBool RestoreBackupWTP(char *WTPDir)\n{\n\tchar cmd_buf[BUF_SIZE];\n\tint ret;\n\n\tWUALog(\"Restoring old WTP...\");\n\n\t/* Del WTPDir content */\n\tret = snprintf(cmd_buf, BUF_SIZE, \"rm -rf %s/*\", WTPDir);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn CW_FALSE;\n\t}\n\n\tSYSTEM_ERR(cmd_buf);\n\n\t/* Restore backup */\n\tret = snprintf(cmd_buf, BUF_SIZE, \"cp -ra %s/* %s/\", BACKUP_DIR, WTPDir);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn CW_FALSE;\n\t}\n\tSYSTEM_ERR(cmd_buf);\n\n\treturn CW_TRUE;\n}\n\nvoid StringToLower(char *str)\n{\n\tfor (; *str != '\\0'; str++)\n\t\t*str = tolower(*str);\n}\n\nCWBool ParseCUD()\n{\n\tFILE *fp;\n\tchar buf[BUF_SIZE];\n\tchar *token;\n\tint ret = CW_TRUE;\n\n\tret = snprintf(buf, BUF_SIZE, \"%s/%s\", CUP_UNPACK_DIR, CUD_FILE_NAME);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn CW_FALSE;\n\t}\n\n\tfp = fopen(buf, \"r\");\n\tif (fp == NULL) {\n\t\tWUALog(\"Error while opening update descriptor.\");\n\t\treturn CW_FALSE;\n\t}\n\n\twhile (fgets(buf, BUF_SIZE, fp) != NULL) {\n\t\ttoken = strtok(buf, \" \");\n\t\tStringToLower(token);\n\t\tif (strncmp(token, \"preupdate\", 9) == 0) {\n\t\t\ttoken = strtok(NULL, \" \");\n\t\t\tif (token == NULL) {\n\t\t\t\tWUALog(\"Error while parsing update descriptor.\");\n\t\t\t\tret = CW_FALSE;\n\t\t\t\tgoto exit_parse;;\n\t\t\t}\n\t\t\tsnprintf(cud.pre_script, BUF_SIZE, \"%s/scripts/%s\", CUP_UNPACK_DIR, token);\n\t\t} else if (strncmp(token, \"postupdate\", 10) == 0) {\n\t\t\ttoken = strtok(NULL, \" \");\n\t\t\tif (token == NULL) {\n\t\t\t\tWUALog(\"Error while parsing update descriptor.\");\n\t\t\t\tret = CW_FALSE;\n\t\t\t\tgoto exit_parse;;\n\t\t\t}\n\t\t\tsnprintf(cud.post_script, BUF_SIZE, \"%s/scripts/%s\", CUP_UNPACK_DIR, token);\n\t\t} else if (strncmp(token, \"version\", 7) == 0) {\n\t\t\ttoken = strtok(NULL, \" \");\n\t\t\tif (token == NULL) {\n\t\t\t\tWUALog(\"Error while parsing update descriptor.\");\n\t\t\t\tret = CW_FALSE;\n\t\t\t\tgoto exit_parse;;\n\t\t\t}\n\t\t\tsnprintf(cud.version, BUF_SIZE, \"%s\", token);\n\t\t}\n\t}\n\n\tif (strlen(cud.version) == 0) {\n\t\tWUALog(\"Error while parsing CUD file, no version specified.\");\n\t\tret = CW_FALSE;\n\t}\n\n exit_parse:\n\tfclose(fp);\n\treturn ret;\n}\n\nvoid CleanTmpFiles(char *cupFile)\n{\n\tint ret;\n\tchar cmd_buf[BUF_SIZE];\n\n\t/* In this function we can afford to ignore return values */\n\n\t/* Remove CUP file */\n\tremove(cupFile);\n\n\t/* Remove Unpack and Backup Directory */\n\tret = snprintf(cmd_buf, BUF_SIZE, \"rm -rf %s %s\", CUP_UNPACK_DIR, BACKUP_DIR);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn;\n\t}\n\n\tret = system(cmd_buf);\n}\n\nCWBool BackupCurrentWTP(char *WTPDir)\n{\n\n\tchar cmd_buf[BUF_SIZE];\n\tint ret;\n\n\tret = snprintf(cmd_buf, BUF_SIZE, \"cp -ar %s/* %s\", WTPDir, BACKUP_DIR);\n\tif (ret < 0 || ret >= BUF_SIZE) {\n\t\treturn CW_FALSE;\n\t}\n\n\tSYSTEM_ERR(cmd_buf);\n\n\treturn CW_TRUE;\n}\n\nCWBool MakeDir(char *dirname)\n{\n\tint ret;\n\n\tret = mkdir(dirname, 0700);\n\tif (ret != 0) {\n\t\tWUALog(\"Can't create directory %s\", dirname);\n\t\treturn CW_FALSE;\n\t}\n\n\treturn CW_TRUE;\n}\n\n/****************************************************************\n * Log Functions\n ****************************************************************/\n\nCWBool WUAInitLog(char *logFile)\n{\n\tif ((log_file = fopen(logFile, \"a\")) == NULL) {\n\t\treturn CW_FALSE;\n\t}\n\treturn CW_TRUE;\n}\n\nvoid WUALog(char *msg, ...)\n{\n\tif (log_file == NULL)\n\t\treturn;\n\n\tchar date_buf[BUF_SIZE] = { '\\0' };\n\ttime_t time_s = time(NULL);\n\tstruct tm *tm_s = localtime(&time_s);\n\tstrftime(date_buf, BUF_SIZE, \"%d/%b/%Y:%H:%M:%S %z\", tm_s);\n\tfprintf(log_file, \"%s: \", date_buf);\n\n\tva_list argp;\n\tva_start(argp, msg);\n\tvfprintf(log_file, msg, argp);\n\tva_end(argp);\n\n\tfprintf(log_file, \"\\n\");\n\n\tfflush(log_file);\n}\n\nvoid WUALogClose()\n{\n\tif (log_file != NULL)\n\t\tfclose(log_file);\n}\n\nvoid daemonize()\n{\n\tpid_t pid;\n\tint sid;\n\n\t/* already a daemon */\n\tif (getppid() == 1)\n\t\treturn;\n\n\t/* Fork off the parent process */\n\tpid = fork();\n\tif (pid < 0) {\n\t\texit(EXIT_FAILURE);\n\t}\n\t/* If we got a good PID, then we can exit the parent process. */\n\tif (pid > 0) {\n\t\texit(EXIT_SUCCESS);\n\t}\n\n\t/* At this point we are executing as the child process */\n\n\t/* Change the file mode mask */\n\tumask(0);\n\n\t/* Create a new SID for the child process */\n\tsid = setsid();\n\tif (sid < 0) {\n\t\texit(EXIT_FAILURE);\n\t}\n\n\t/* Redirect standard files to /dev/null */\n\tfreopen(\"/dev/null\", \"r\", stdin);\n\tfreopen(\"/dev/null\", \"w\", stdout);\n\tfreopen(\"/dev/null\", \"w\", stderr);\n}\n"
  },
  {
    "path": "WUM.h",
    "content": "/*\n * WUM.h - WTP Update Messages\n *\n *\n * 4/11/2009 - Donato Capitella (d.capitella@gmail.com)\n */\n\n#ifndef WUM_H\n#define WUM_H\n\n#include \"CWCommon.h\"\n\n#define WTP_VERSION_MAJOR   0\n#define WTP_VERSION_MINOR   93\n#define WTP_VERSION_REVISION    2\n\n#define WTP_VERSION_REQUEST 1\n#define WTP_VERSION_RESPONSE    2\n\n#define WTP_UPDATE_REQUEST      3\n#define WTP_UPDATE_RESPONSE     4\n\n#define WTP_CUP_FRAGMENT        5\n#define WTP_CUP_ACK         6\n\n#define WTP_COMMIT_UPDATE   7\n#define WTP_COMMIT_ACK          8\n\n#define WTP_CANCEL_UPDATE_REQUEST   9\n#define WTP_CANCEL_UPDATE_RESPONSE  10\n\n#define WTP_LOCK_FILE           \"wtp.lock\"\n\nvoid WTPUpdateAgent(char *CupPath);\n\n#endif\t\t\t\t/* WUM_H */\n"
  },
  {
    "path": "capwap_bugfix_0.01",
    "content": "\n  ___                    ____                               \n / _ \\ _ __   ___ _ __  / ___|__ _ _ ____      ____ _ _ __  \n| | | | '_ \\ / _ \\ '_ \\| |   / _` | '_ \\ \\ /\\ / / _` | '_ \\ \n| |_| | |_) |  __/ | | | |__| (_| | |_) \\ V  V / (_| | |_) |\n \\___/| .__/ \\___|_| |_|\\____\\__,_| .__/ \\_/\\_/ \\__,_| .__/ \n      |_|                         |_|BUGFIX 0.01     |_|\n                         \nby mty (Matteo Latini, mtylty@gmail.com)\n\n\n\nThis stuff \"\"\"should\"\"\" now work the way is intended below...Please don't be harsh!!! :)\n\n===> WTP re-enters Discovery State when session times out (WTPRunstate.c in CWWTPManageGenericRunMessage when using CWResetTimers) <===\n\n===> Fixed Segfault when using configuration tags missing preceding whitespace (ACConfigFile.c and WTPConfigFile.c) <===\n\n===> *** Neighbour Dead interval timeout is now down to 70 (previous value 200). DTLS doesn't complain anymore about wrong format certificates when\n     Neighbour Dead interval timeout drops below 200. Please read the quick note to know more... *** <===\n\n===> WTP won't crash anymore when changing the status of the interface on which its socket is binded. Now it simply reenters discovery state with\n     a reset <=== \n\n\n\n\n*** Quick Note: \n        It should be possible (in my opinion) to lower the Neighbour Dead interval timeout even more... WARNING! Before doing so, another bugfix \n        will be required. Infact, by running some tests, I found a bug (???) which I could not fix. Essentially, the problem lays in a concurrent\n        thread-wait-for-condition function of both WTP and AC, after the Neighbour dead interval alarm has been started on both daemons.\n        The condition (if I got it correctly) is just the daemon waiting for some frames on the interface. Since both daemons are waiting to hear\n        from each other, they take some time to unlock... So, if the neighbour dead interval timeout is too low, they both (the AC and the WTP) get\n        stuck in an endless loop (every time the timeout reaches zero the AC will think the WTP is dead so it will close the DTLS session while the \n        WTP is still waiting to send Echo requests to the AC).\n        The current setting (70) is the value I found working in all my tests. \n        DISCLAIMER: Since all tests I made were carried out on my home LAN, maybe a value below 70 is even possible (or maybe my LAN did not work\n                    properly during the tests and this isn't a bug at all..) \n\n\n\n        In case you were curious, this is the code (or at least this is where it got stuck (checked it with gdb)): \n\n            AC Side (Function CWManageWTP inside ACMainLoop.c):\n\n                /* Wait WTP action */\n                CWThreadMutexLock(&gWTPs[i].interfaceMutex);\n\n                while ((gWTPs[i].isRequestClose == CW_FALSE) &&\n                    (CWGetCountElementFromSafeList(gWTPs[i].packetReceiveList) == 0) &&\n                    (gWTPs[i].interfaceCommand == NO_CMD)) {\n\n                     /*TODO: Check system */\n                    CWWaitThreadCondition(&gWTPs[i].interfaceWait, \n                                  &gWTPs[i].interfaceMutex);\n                }\n\n                CWThreadMutexUnlock(&gWTPs[i].interfaceMutex);\n\n\n\n\n            WTP Side (Function CWManageWTP inside ACMainLoop.c):\n\n                /*\n                 * if there are no frames from stations\n                 * and no packets from AC...\n                 */\n                if ((CWGetCountElementFromSafeList(gPacketReceiveList) == 0) && (CWGetCountElementFromSafeList(gFrameList) == 0)) {\n                    /*\n                     * ...wait at most 4 mins for a frame or packet.\n                     */\n                    if (!CWErr(CWWaitThreadConditionTimeout(&gInterfaceWait, &gInterfaceMutex, &timenow))) {\n\n                        CWThreadMutexUnlock(&gInterfaceMutex);\n            \n                        if (CWErrorGetLastErrorCode() == CW_ERROR_TIME_EXPIRED) {\n\n                            CWLog(\"No Message from AC for a long time... restart Discovery State\");\n                            break;\n                        }\n                        continue;\n                    }\n                }\n"
  },
  {
    "path": "changeLog-0.92",
    "content": "OpenCapWap 0.92 - 27/10/2009\nDonato Capitella - d.capitella@gmail.com\n\nThis version corrects 18 bugs mainly related to resource leakages in the WTP.\nHere follows a brief report:\n\nNote:   TRL(Thread Resource Leakage)\n    ML (Memory Leak)\n    LE (Logic Error)\n    UMR (Uninitialized Memory Rea)\n\n(Descriptions about each bug can be found in the source code)\n\nTRL01   -   ACInterface.c\nLE01    -   ACInterface.c\nML01    -   WTPRunState.c\nTRL02   -   timerlib.c\nML02    -   WTPConfigureState.c\nML03    -   WTPJoinState.c\nML04    -   WTPConfigureState.c\nML05    -   WTPConfigureState.c\nML06    -   WTPProtocol.c\nLE02    -   CWConfigFile.c\nML07    -   WTPJoinState.c\nML08    -   WTPJoinState.c\nML09    -   WTPProtocol.c\nUMR02   -   WTPFrameReceive.c\nLE03    -   CWStevens.c\nML11    -   ACDiscoveryState.c\nML12    -   ACRetransmission.c\nUMR03   -   ACMainLoop.c\n\n"
  },
  {
    "path": "changeLog-0.93",
    "content": "OpenCapWap 0.93.3 - 02/12/2009\nDonato Capitella - d.capitella@gmail.com\n\nThis version adds a vendor specific WTP Update System together with\nsome minor bugfixes. \n\n*----------------------------*\n|      WTP Update System     |\n*----------------------------*\nThe update system consists of a tool used AC-side to send\nupdates (wum) and an update agent (WUA) executed WTP-side which\ntakes care of installing an update package. \n\n*** WUA ***\nThe WUA can be compiled like this:\n\n$ make WUA \n\nOnce compiled, it has to be reside in the same directory as the WTP binary.\n\n*** wum ***\nThe wum commmad source code is located in the /wum sub-directory. To \ncompile it, just cd into /wum and then execute 'make'. This command\ncan be installed anywhere on the AC machine and it relies on the\nAC Interface to operate.\n\nFor further information about the update system and how update packages\nare biult, refer to the document WTPUpdateSystem.pdf in the /docs sub-directory \nin this source tree.\n\n*---------------------------*\nNote about log location\n*---------------------------*\nFrom this version on, WTP and AC logs are stored in /var/log/.\nThis behaviour can be changed editing the header files CWAC.h and\nCWWTP.h before building Open CAPWAP.\n\n"
  },
  {
    "path": "changeLog-0.93.3",
    "content": "OpenCAPWAP 0.93.3 - 03/02/2010\nElena Agostini & Donato Capitella\n\nA bug in timerlib.c was identified and corrected. This bug caused a pointer to be freed multiple times.\nFiles changed:\ntimerlib.c - LE-03-02-2010.01\nCWThread.c - LE-03-02-2010.01  \nCWThread.c - LE-03-02-2010.02\n\n"
  },
  {
    "path": "client.pem",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQDNo9iIeIifo0astEKSDLU/TsIVckZ4/K/b/8KrZ6cE6Lx7wROE\nu/QWjEXYe6nPRX80TeQ4zEe989QMLkD9p28binly7c8SyGNMlTGKLDksNndVMa1r\nbXS+XxeqJ6I1VDe7c42jb9E4wzgpCkHlitG+r/va9rx+GqHVZFs05YctVQIDAQAB\nAoGAVa7ea0alzrZunUlir44h+yXq0prR6FmJQQaZa2f9/Jqo5nu1kUnrU3XRKHmm\ncJnJfdaysEPV5Lzy7rxbEhWwwi6vq5gvPWkRgJ5VLFQv3/l65+ZLgq3E9a9pv6uz\nAG77YDzHuTKpc5o0Nc1G+vvdsklAM3RwA0TRXmcDMj9EZYUCQQDsXKkdfuoZGzj+\na6nlV7SaiANuG9WSTBoFAbJtKDBOm8HucvjmnrCD8NRRz8zMJZ86E6vdPyotOAy1\n92DgSD8HAkEA3rm9cxml08Ar9xes1WCIbKFaskJBXfOAOhqgUBMjbMDo4MgS2L8f\n+TszJPsUfXRLRRjEdEpSZDl7gOqIk5G9wwJAR6MB4p2vp/JXQM0yzf7aDygAGiQ3\ng8Kq9C+Ce5D9qyWMDpAsHgGksCiSwUUA5jLU4o5JvaHCT7g4KgKTCwb6iwJBAMSs\nQXV07XC5nlkYB9932aALL3p/dRdQYSdtwahT7hEnm7x6D+Jjiwla1EPQjvxlB95h\nC4Eg6/ZiqANjluywYl8CQFn3HbACM4//Yy0Z50gvokERAYW9W/94J+4W3siB4lmC\nFBa29h7GVu0Zt1G9OQBfi0dmp2UN3NjfZaCrhXAShTQ=\n-----END RSA PRIVATE KEY-----\nCertificate:\n    Data:\n        Version: 3 (0x2)\n        Serial Number: 2 (0x2)\n        Signature Algorithm: md5WithRSAEncryption\n        Issuer: CN=Local CAPWAP Root Certificate Authority, ST=Some State, C=IT/emailAddress=root@somename.somewhere.com, O=Root Certificate Authority, OU=My Subunit of Large Organization\n        Validity\n            Not Before: Oct  5 09:58:10 2006 GMT\n            Not After : Oct  4 09:58:10 2011 GMT\n        Subject: CN=somename.somewhere.com, ST=Some State, C=IT/emailAddress=root@somename.somewhere.com, O=My Large Organization Name, OU=My Subunit of Large Organization\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n            RSA Public Key: (1024 bit)\n                Modulus (1024 bit):\n                    00:cd:a3:d8:88:78:88:9f:a3:46:ac:b4:42:92:0c:\n                    b5:3f:4e:c2:15:72:46:78:fc:af:db:ff:c2:ab:67:\n                    a7:04:e8:bc:7b:c1:13:84:bb:f4:16:8c:45:d8:7b:\n                    a9:cf:45:7f:34:4d:e4:38:cc:47:bd:f3:d4:0c:2e:\n                    40:fd:a7:6f:1b:8a:79:72:ed:cf:12:c8:63:4c:95:\n                    31:8a:2c:39:2c:36:77:55:31:ad:6b:6d:74:be:5f:\n                    17:aa:27:a2:35:54:37:bb:73:8d:a3:6f:d1:38:c3:\n                    38:29:0a:41:e5:8a:d1:be:af:fb:da:f6:bc:7e:1a:\n                    a1:d5:64:5b:34:e5:87:2d:55\n                Exponent: 65537 (0x10001)\n        X509v3 extensions:\n            X509v3 Extended Key Usage: \n                1.3.6.1.5.5.7.3.19\n            Netscape Cert Type: \n                SSL Client\n            X509v3 Subject Alternative Name: \n                DNS:altname.somewhere.com\n            X509v3 Basic Constraints: \n                CA:FALSE\n    Signature Algorithm: md5WithRSAEncryption\n        91:b8:93:f1:01:49:44:55:7d:09:f1:d8:69:7e:5f:bf:a5:7a:\n        a0:f5:32:5f:8a:df:47:0d:87:b8:da:76:49:17:24:6b:e0:fd:\n        67:b4:43:8c:1d:c6:68:d3:82:7f:0c:b5:48:80:af:3a:58:fd:\n        73:99:dc:f5:b8:17:af:99:6d:ce:0e:19:e9:a5:74:03:90:c9:\n        02:e4:72:b2:56:07:43:67:61:8b:33:da:5a:b5:39:dc:c9:eb:\n        f2:5f:10:35:c5:14:18:ac:3f:f5:70:a6:63:c6:d4:0c:d4:f7:\n        4d:6f:ea:2d:0d:6f:4a:65:27:af:ff:b7:9f:fa:d0:83:8d:a2:\n        df:a3\n-----BEGIN CERTIFICATE-----\nMIIDXjCCAsegAwIBAgIBAjANBgkqhkiG9w0BAQQFADCB0DEwMC4GA1UEAxMnTG9j\nYWwgQ0FQV0FQIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRMwEQYDVQQIEwpT\nb21lIFN0YXRlMQswCQYDVQQGEwJJVDEqMCgGCSqGSIb3DQEJARYbcm9vdEBzb21l\nbmFtZS5zb21ld2hlcmUuY29tMSMwIQYDVQQKExpSb290IENlcnRpZmljYXRlIEF1\ndGhvcml0eTEpMCcGA1UECxMgTXkgU3VidW5pdCBvZiBMYXJnZSBPcmdhbml6YXRp\nb24wHhcNMDYxMDA1MDk1ODEwWhcNMTExMDA0MDk1ODEwWjCBvzEfMB0GA1UEAxMW\nc29tZW5hbWUuc29tZXdoZXJlLmNvbTETMBEGA1UECBMKU29tZSBTdGF0ZTELMAkG\nA1UEBhMCSVQxKjAoBgkqhkiG9w0BCQEWG3Jvb3RAc29tZW5hbWUuc29tZXdoZXJl\nLmNvbTEjMCEGA1UEChMaTXkgTGFyZ2UgT3JnYW5pemF0aW9uIE5hbWUxKTAnBgNV\nBAsTIE15IFN1YnVuaXQgb2YgTGFyZ2UgT3JnYW5pemF0aW9uMIGfMA0GCSqGSIb3\nDQEBAQUAA4GNADCBiQKBgQDNo9iIeIifo0astEKSDLU/TsIVckZ4/K/b/8KrZ6cE\n6Lx7wROEu/QWjEXYe6nPRX80TeQ4zEe989QMLkD9p28binly7c8SyGNMlTGKLDks\nNndVMa1rbXS+XxeqJ6I1VDe7c42jb9E4wzgpCkHlitG+r/va9rx+GqHVZFs05Yct\nVQIDAQABo1cwVTATBgNVHSUEDDAKBggrBgEFBQcDEzARBglghkgBhvhCAQEEBAMC\nB4AwIAYDVR0RBBkwF4IVYWx0bmFtZS5zb21ld2hlcmUuY29tMAkGA1UdEwQCMAAw\nDQYJKoZIhvcNAQEEBQADgYEAkbiT8QFJRFV9CfHYaX5fv6V6oPUyX4rfRw2HuNp2\nSRcka+D9Z7RDjB3GaNOCfwy1SICvOlj9c5nc9bgXr5ltzg4Z6aV0A5DJAuRyslYH\nQ2dhizPaWrU53Mnr8l8QNcUUGKw/9XCmY8bUDNT3TW/qLQ1vSmUnr/+3n/rQg42i\n36M=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "common.h",
    "content": "/*\n * wpa_supplicant/hostapd / common helper functions, etc.\n * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n#ifndef COMMON_H\n#define COMMON_H\n\n#include \"os.h\"\n\n#if defined(__linux__) || defined(__GLIBC__)\n#include <endian.h>\n#include <byteswap.h>\n#endif\t\t\t\t/* __linux__ */\n\n#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \\\n    defined(__OpenBSD__)\n#include <sys/types.h>\n#include <sys/endian.h>\n#define __BYTE_ORDER    _BYTE_ORDER\n#define __LITTLE_ENDIAN _LITTLE_ENDIAN\n#define __BIG_ENDIAN    _BIG_ENDIAN\n#ifdef __OpenBSD__\n#define bswap_16 swap16\n#define bswap_32 swap32\n#define bswap_64 swap64\n#else\t\t\t\t/* __OpenBSD__ */\n#define bswap_16 bswap16\n#define bswap_32 bswap32\n#define bswap_64 bswap64\n#endif\t\t\t\t/* __OpenBSD__ */\n#endif\t\t\t\t/* defined(__FreeBSD__) || defined(__NetBSD__) ||\n\t\t\t\t * defined(__DragonFly__) || defined(__OpenBSD__) */\n\n#ifdef __APPLE__\n#include <sys/types.h>\n#include <machine/endian.h>\n#define __BYTE_ORDER    _BYTE_ORDER\n#define __LITTLE_ENDIAN _LITTLE_ENDIAN\n#define __BIG_ENDIAN    _BIG_ENDIAN\nstatic inline unsigned short bswap_16(unsigned short v)\n{\n\treturn ((v & 0xff) << 8) | (v >> 8);\n}\n\nstatic inline unsigned int bswap_32(unsigned int v)\n{\n\treturn ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24);\n}\n#endif\t\t\t\t/* __APPLE__ */\n\n#ifdef CONFIG_TI_COMPILER\n#define __BIG_ENDIAN 4321\n#define __LITTLE_ENDIAN 1234\n#ifdef __big_endian__\n#define __BYTE_ORDER __BIG_ENDIAN\n#else\n#define __BYTE_ORDER __LITTLE_ENDIAN\n#endif\n#endif\t\t\t\t/* CONFIG_TI_COMPILER */\n\n#ifdef __SYMBIAN32__\n#define __BIG_ENDIAN 4321\n#define __LITTLE_ENDIAN 1234\n#define __BYTE_ORDER __LITTLE_ENDIAN\n#endif\t\t\t\t/* __SYMBIAN32__ */\n\n#ifdef CONFIG_NATIVE_WINDOWS\n#include <winsock.h>\n\ntypedef int socklen_t;\n\n#ifndef MSG_DONTWAIT\n#define MSG_DONTWAIT 0\t\t/* not supported */\n#endif\n\n#endif\t\t\t\t/* CONFIG_NATIVE_WINDOWS */\n\n#ifdef _MSC_VER\n#define inline __inline\n\n#undef vsnprintf\n#define vsnprintf _vsnprintf\n#undef close\n#define close closesocket\n#endif\t\t\t\t/* _MSC_VER */\n\n/* Define platform specific integer types */\n\n#ifdef _MSC_VER\ntypedef UINT64 u64;\ntypedef UINT32 u32;\ntypedef UINT16 u16;\ntypedef UINT8 u8;\ntypedef INT64 s64;\ntypedef INT32 s32;\ntypedef INT16 s16;\ntypedef INT8 s8;\n#define WPA_TYPES_DEFINED\n#endif\t\t\t\t/* _MSC_VER */\n\n#ifdef __vxworks\ntypedef unsigned long long u64;\ntypedef UINT32 u32;\ntypedef UINT16 u16;\ntypedef UINT8 u8;\ntypedef long long s64;\ntypedef INT32 s32;\ntypedef INT16 s16;\ntypedef INT8 s8;\n#define WPA_TYPES_DEFINED\n#endif\t\t\t\t/* __vxworks */\n\n#ifdef CONFIG_TI_COMPILER\n#ifdef _LLONG_AVAILABLE\ntypedef unsigned long long u64;\n#else\n/*\n * TODO: 64-bit variable not available. Using long as a workaround to test the\n * build, but this will likely not work for all operations.\n */\ntypedef unsigned long u64;\n#endif\ntypedef unsigned int u32;\ntypedef unsigned short u16;\ntypedef unsigned char u8;\n#define WPA_TYPES_DEFINED\n#endif\t\t\t\t/* CONFIG_TI_COMPILER */\n\n#ifdef __SYMBIAN32__\n#define __REMOVE_PLATSEC_DIAGNOSTICS__\n#include <e32def.h>\ntypedef TUint64 u64;\ntypedef TUint32 u32;\ntypedef TUint16 u16;\ntypedef TUint8 u8;\n#define WPA_TYPES_DEFINED\n#endif\t\t\t\t/* __SYMBIAN32__ */\n\n#ifndef WPA_TYPES_DEFINED\n#ifdef CONFIG_USE_INTTYPES_H\n#include <inttypes.h>\n#else\n#include <stdint.h>\n#endif\ntypedef uint64_t u64;\ntypedef uint32_t u32;\ntypedef uint16_t u16;\ntypedef uint8_t u8;\ntypedef int64_t s64;\ntypedef int32_t s32;\ntypedef int16_t s16;\ntypedef int8_t s8;\n#define WPA_TYPES_DEFINED\n#endif\t\t\t\t/* !WPA_TYPES_DEFINED */\n\n/* Define platform specific byte swapping macros */\n\n#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)\n\nstatic inline unsigned short wpa_swap_16(unsigned short v)\n{\n\treturn ((v & 0xff) << 8) | (v >> 8);\n}\n\nstatic inline unsigned int wpa_swap_32(unsigned int v)\n{\n\treturn ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24);\n}\n\n#define le_to_host16(n) (n)\n#define host_to_le16(n) (n)\n#define be_to_host16(n) wpa_swap_16(n)\n#define host_to_be16(n) wpa_swap_16(n)\n#define le_to_host32(n) (n)\n#define be_to_host32(n) wpa_swap_32(n)\n#define host_to_be32(n) wpa_swap_32(n)\n\n#define WPA_BYTE_SWAP_DEFINED\n\n#endif\t\t\t\t/* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */\n\n#ifndef WPA_BYTE_SWAP_DEFINED\n\n#ifndef __BYTE_ORDER\n#ifndef __LITTLE_ENDIAN\n#ifndef __BIG_ENDIAN\n#define __LITTLE_ENDIAN 1234\n#define __BIG_ENDIAN 4321\n#if defined(sparc)\n#define __BYTE_ORDER __BIG_ENDIAN\n#endif\n#endif\t\t\t\t/* __BIG_ENDIAN */\n#endif\t\t\t\t/* __LITTLE_ENDIAN */\n#endif\t\t\t\t/* __BYTE_ORDER */\n\n#if __BYTE_ORDER == __LITTLE_ENDIAN\n#define le_to_host16(n) ((__force u16) (le16) (n))\n#define host_to_le16(n) ((__force le16) (u16) (n))\n#define be_to_host16(n) bswap_16((__force u16) (be16) (n))\n#define host_to_be16(n) ((__force be16) bswap_16((n)))\n#define le_to_host32(n) ((__force u32) (le32) (n))\n#define host_to_le32(n) ((__force le32) (u32) (n))\n#define be_to_host32(n) bswap_32((__force u32) (be32) (n))\n#define host_to_be32(n) ((__force be32) bswap_32((n)))\n#define le_to_host64(n) ((__force u64) (le64) (n))\n#define host_to_le64(n) ((__force le64) (u64) (n))\n#define be_to_host64(n) bswap_64((__force u64) (be64) (n))\n#define host_to_be64(n) ((__force be64) bswap_64((n)))\n#elif __BYTE_ORDER == __BIG_ENDIAN\n#define le_to_host16(n) bswap_16(n)\n#define host_to_le16(n) bswap_16(n)\n#define be_to_host16(n) (n)\n#define host_to_be16(n) (n)\n#define le_to_host32(n) bswap_32(n)\n#define be_to_host32(n) (n)\n#define host_to_be32(n) (n)\n#define le_to_host64(n) bswap_64(n)\n#define host_to_le64(n) bswap_64(n)\n#define be_to_host64(n) (n)\n#define host_to_be64(n) (n)\n#ifndef WORDS_BIGENDIAN\n#define WORDS_BIGENDIAN\n#endif\n#else\n#error Could not determine CPU byte order\n#endif\n\n#define WPA_BYTE_SWAP_DEFINED\n#endif\t\t\t\t/* !WPA_BYTE_SWAP_DEFINED */\n\n/* Macros for handling unaligned memory accesses */\n\n#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))\n#define WPA_PUT_BE16(a, val)            \\\n    do {                    \\\n        (a)[0] = ((u16) (val)) >> 8;    \\\n        (a)[1] = ((u16) (val)) & 0xff;  \\\n    } while (0)\n\n#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))\n#define WPA_PUT_LE16(a, val)            \\\n    do {                    \\\n        (a)[1] = ((u16) (val)) >> 8;    \\\n        (a)[0] = ((u16) (val)) & 0xff;  \\\n    } while (0)\n\n#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \\\n             ((u32) (a)[2]))\n#define WPA_PUT_BE24(a, val)                    \\\n    do {                            \\\n        (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff);   \\\n        (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);    \\\n        (a)[2] = (u8) (((u32) (val)) & 0xff);       \\\n    } while (0)\n\n#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \\\n             (((u32) (a)[2]) << 8) | ((u32) (a)[3]))\n#define WPA_PUT_BE32(a, val)                    \\\n    do {                            \\\n        (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff);   \\\n        (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff);   \\\n        (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff);    \\\n        (a)[3] = (u8) (((u32) (val)) & 0xff);       \\\n    } while (0)\n\n#define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \\\n             (((u32) (a)[1]) << 8) | ((u32) (a)[0]))\n#define WPA_PUT_LE32(a, val)                    \\\n    do {                            \\\n        (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff);   \\\n        (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff);   \\\n        (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);    \\\n        (a)[0] = (u8) (((u32) (val)) & 0xff);       \\\n    } while (0)\n\n#define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \\\n             (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \\\n             (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \\\n             (((u64) (a)[6]) << 8) | ((u64) (a)[7]))\n#define WPA_PUT_BE64(a, val)                \\\n    do {                        \\\n        (a)[0] = (u8) (((u64) (val)) >> 56);    \\\n        (a)[1] = (u8) (((u64) (val)) >> 48);    \\\n        (a)[2] = (u8) (((u64) (val)) >> 40);    \\\n        (a)[3] = (u8) (((u64) (val)) >> 32);    \\\n        (a)[4] = (u8) (((u64) (val)) >> 24);    \\\n        (a)[5] = (u8) (((u64) (val)) >> 16);    \\\n        (a)[6] = (u8) (((u64) (val)) >> 8); \\\n        (a)[7] = (u8) (((u64) (val)) & 0xff);   \\\n    } while (0)\n\n#define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \\\n             (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \\\n             (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \\\n             (((u64) (a)[1]) << 8) | ((u64) (a)[0]))\n\n#ifndef ETH_ALEN\n#define ETH_ALEN 6\n#endif\n#ifndef IFNAMSIZ\n#define IFNAMSIZ 16\n#endif\n#ifndef ETH_P_ALL\n#define ETH_P_ALL 0x0003\n#endif\n#ifndef ETH_P_80211_ENCAP\n#define ETH_P_80211_ENCAP 0x890d\t/* TDLS comes under this category */\n#endif\n#ifndef ETH_P_PAE\n#define ETH_P_PAE 0x888E\t/* Port Access Entity (IEEE 802.1X) */\n#endif\t\t\t\t/* ETH_P_PAE */\n#ifndef ETH_P_EAPOL\n#define ETH_P_EAPOL ETH_P_PAE\n#endif\t\t\t\t/* ETH_P_EAPOL */\n#ifndef ETH_P_RSN_PREAUTH\n#define ETH_P_RSN_PREAUTH 0x88c7\n#endif\t\t\t\t/* ETH_P_RSN_PREAUTH */\n#ifndef ETH_P_RRB\n#define ETH_P_RRB 0x890D\n#endif\t\t\t\t/* ETH_P_RRB */\n\n#ifdef __GNUC__\n#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))\n#define STRUCT_PACKED __attribute__ ((packed))\n#else\n#define PRINTF_FORMAT(a,b)\n#define STRUCT_PACKED\n#endif\n\n#ifdef CONFIG_ANSI_C_EXTRA\n\n#if !defined(_MSC_VER) || _MSC_VER < 1400\n/* snprintf - used in number of places; sprintf() is _not_ a good replacement\n * due to possible buffer overflow; see, e.g.,\n * http://www.ijs.si/software/snprintf/ for portable implementation of\n * snprintf. */\nint snprintf(char *str, size_t size, const char *format, ...);\n\n/* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */\nint vsnprintf(char *str, size_t size, const char *format, va_list ap);\n#endif\t\t\t\t/* !defined(_MSC_VER) || _MSC_VER < 1400 */\n\n/* getopt - only used in main.c */\nint getopt(int argc, char *const argv[], const char *optstring);\nextern char *optarg;\nextern int optind;\n\n#ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF\n#ifndef __socklen_t_defined\ntypedef int socklen_t;\n#endif\n#endif\n\n/* inline - define as __inline or just define it to be empty, if needed */\n#ifdef CONFIG_NO_INLINE\n#define inline\n#else\n#define inline __inline\n#endif\n\n#ifndef __func__\n#define __func__ \"__func__ not defined\"\n#endif\n\n#ifndef bswap_16\n#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff))\n#endif\n\n#ifndef bswap_32\n#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \\\n             (((u32) (a) << 8) & 0xff0000) | \\\n                 (((u32) (a) >> 8) & 0xff00) | \\\n                 (((u32) (a) >> 24) & 0xff))\n#endif\n\n#ifndef MSG_DONTWAIT\n#define MSG_DONTWAIT 0\n#endif\n\n#ifdef _WIN32_WCE\nvoid perror(const char *s);\n#endif\t\t\t\t/* _WIN32_WCE */\n\n#endif\t\t\t\t/* CONFIG_ANSI_C_EXTRA */\n\n#ifndef MAC2STR\n#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]\n#define MACSTR \"%02x:%02x:%02x:%02x:%02x:%02x\"\n\n/*\n * Compact form for string representation of MAC address\n * To be used, e.g., for constructing dbus paths for P2P Devices\n */\n#define COMPACT_MACSTR \"%02x%02x%02x%02x%02x%02x\"\n#endif\n\n#ifndef BIT\n#define BIT(x) (1 << (x))\n#endif\n\n/*\n * Definitions for sparse validation\n * (http://kernel.org/pub/linux/kernel/people/josh/sparse/)\n */\n#ifdef __CHECKER__\n#define __force __attribute__((force))\n#define __bitwise __attribute__((bitwise))\n#else\n#define __force\n#define __bitwise\n#endif\n\ntypedef u16 __bitwise be16;\ntypedef u16 __bitwise le16;\ntypedef u32 __bitwise be32;\ntypedef u32 __bitwise le32;\ntypedef u64 __bitwise be64;\ntypedef u64 __bitwise le64;\n\n#ifndef __must_check\n#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)\n#define __must_check __attribute__((__warn_unused_result__))\n#else\n#define __must_check\n#endif\t\t\t\t/* __GNUC__ */\n#endif\t\t\t\t/* __must_check */\n\nint hwaddr_aton(const char *txt, u8 * addr);\nint hwaddr_compact_aton(const char *txt, u8 * addr);\nint hwaddr_aton2(const char *txt, u8 * addr);\nint hex2byte(const char *hex);\nint hexstr2bin(const char *hex, u8 * buf, size_t len);\nvoid inc_byte_array(u8 * counter, size_t len);\nvoid wpa_get_ntp_timestamp(u8 * buf);\nint wpa_snprintf_hex(char *buf, size_t buf_size, const u8 * data, size_t len);\nint wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 * data, size_t len);\n\n#ifdef CONFIG_NATIVE_WINDOWS\nvoid wpa_unicode2ascii_inplace(TCHAR * str);\nTCHAR *wpa_strdup_tchar(const char *str);\n#else\t\t\t\t/* CONFIG_NATIVE_WINDOWS */\n#define wpa_unicode2ascii_inplace(s) do { } while (0)\n#define wpa_strdup_tchar(s) strdup((s))\n#endif\t\t\t\t/* CONFIG_NATIVE_WINDOWS */\n\nconst char *wpa_ssid_txt(const u8 * ssid, size_t ssid_len);\n\nstatic inline int is_zero_ether_addr(const u8 * a)\n{\n\treturn !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]);\n}\n\nstatic inline int is_broadcast_ether_addr(const u8 * a)\n{\n\treturn (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff;\n}\n\n#define broadcast_ether_addr (const u8 *) \"\\xff\\xff\\xff\\xff\\xff\\xff\"\n\n//#include \"wpa_debug.h\"\n\n/*\n * gcc 4.4 ends up generating strict-aliasing warnings about some very common\n * networking socket uses that do not really result in a real problem and\n * cannot be easily avoided with union-based type-punning due to struct\n * definitions including another struct in system header files. To avoid having\n * to fully disable strict-aliasing warnings, provide a mechanism to hide the\n * typecast from aliasing for now. A cleaner solution will hopefully be found\n * in the future to handle these cases.\n */\nvoid *__hide_aliasing_typecast(void *foo);\n#define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a))\n\n#ifdef CONFIG_VALGRIND\n#include <valgrind/memcheck.h>\n#define WPA_MEM_DEFINED(ptr, len) VALGRIND_MAKE_MEM_DEFINED((ptr), (len))\n#else\t\t\t\t/* CONFIG_VALGRIND */\n#define WPA_MEM_DEFINED(ptr, len) do { } while (0)\n#endif\t\t\t\t/* CONFIG_VALGRIND */\n\n#endif\t\t\t\t/* COMMON_H */\n"
  },
  {
    "path": "config.ac",
    "content": "# Config File for AC. Lines beginning with # and blank lines will be ignored\n\n# HW version of the AC\n</AC_HW_VERSION> 1235656\n\n# SW version of the AC\n</AC_SW_VERSION> 3256984\n\n# Max number of mobile stations supported\n</AC_MAX_STATIONS> 200\n\n# Max number of WTP supported\n</AC_MAX_WTPS> 15\n\n# Authentication mode for AC. Can be X509_CERTIFICATE or PRESHARED (for\n# preshared keys)\n#</AC_SECURITY> X509_CERTIFICATE\n</AC_SECURITY> PRESHARED\n\n# Can be IPv4 or IPv6. Of course the host must have IPv6 enabled to work with the\n# setting IPv6\n</AC_LEV3_PROTOCOL> IPv4\n\n# Force MTU to 50 bytes, used to debug fragmentation ;-) If you don't need this, simply\n# comment the line by adding a #.\n</AC_FORCE_MTU> 1420\n\n</AC_NAME> My AC\n\n# The AC will join the Multicast Groups you add here\n<AC_MCAST_GROUPS>\n#239.255.1.2\n#239.255.1.3\n</AC_MCAST_GROUPS>\n\n</AC_LOG_FILE_ENABLE> 1\n\n</AC_LOG_FILE_SIZE> 30000000\n"
  },
  {
    "path": "config.wtp",
    "content": "\n# Config File for WTP. Lines beginning with # and blank lines will be ignored\n\n# List of ACs' addresses for Discovery. They can be host names (e.g. \"localhost\",\n# IPv4 addresses if we are an IPv4 host or IPv6 addresses if we are an\n# IPv6Host. Wecan also add limited broadcast address (255.255.255.255) or\n# multicast addresses\n<AC_ADDRESSES>\n#255.255.255.255\n#localhost\n#192.168.1.2\n#192.168.1.8\n#239.255.1.3\n172.16.151.1\n#127.0.0.1\n#10.10.3.252\n#1.1.1.2\n#172.16.1.104\n#localhost\n</AC_ADDRESSES>\n\n</WTP_NAME>My WTP 1\n</WTP_LOCATION>  Next to Fridge\n\n# Can be IPv4 or IPv6. Of course the host must have IPv6 enabled to work with the\n# setting IPv6\n</WTP_LEV3_PROTOCOL> IPv4\n\n# Force MTU to 50 bytes, used to debug fragmentation ;-) If you don't need this, simply\n# comment the line by adding a #.\n</WTP_FORCE_MTU> 1420\n\n# If you uncomment the following line, the WTP will jump to Join State\n# (without doing Discovery) and the address will be considered the AC's address.\n#</WTP_FORCE_AC_ADDRESS> 192.168.1.2\n\n# Usually the WTP knows if the AC supports Certificate or Preshared-keys authentication\n# from the Discovery Response. If we jump to the Join State using </WTP_FORCE_AC_ADDRESS>,\n# however, we must know how to behave. This setting can be X509_CERTIFICATE (default if you\n# leave the line commented) or PRESHARED. This setting is ignored if you don't use\n# </WTP_FORCE_AC_ADDRESS>.\n#</WTP_FORCE_SECURITY> PRESHARED\n</WTP_FORCE_SECURITY> X509_CERTIFICATE\n\n</AC_LOG_FILE_ENABLE> 1\n\n</AC_LOG_FILE_SIZE> 8388608\n\n"
  },
  {
    "path": "configure.ac",
    "content": "AC_INIT([opencapwap], [1.0], [info@travelping.com])\nAM_INIT_AUTOMAKE([1.9 foreign silent-rules])\nAC_CONFIG_MACRO_DIR([m4])\nAC_USE_SYSTEM_EXTENSIONS\n\nLT_INIT\n\nAM_CONFIG_HEADER(config.h)\nAC_PREFIX_DEFAULT(/usr)\n\nAC_CANONICAL_HOST\nAC_USE_SYSTEM_EXTENSIONS\n\nAM_SILENT_RULES([yes])\n\nAC_PROG_LIBTOOL\n\nAC_PROG_CC\nAC_PROG_CC_C99\nAM_PROG_CC_C_O\n\nAC_PROG_INSTALL\nAC_SET_MAKE\n\nAC_CHECK_HEADER([pthread.h], [], [AC_MSG_ERROR(You need the pthread headers)])\nAC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR(You need the pthread library)])\n\nAC_CHECK_FUNC([sem_timedwait], [AC_DEFINE([HAVE_SEM_TIMEDWAIT], [1],\n                               [Define if sem_timedwait exists.])])\n\nAC_ARG_ENABLE([debug],\n    AS_HELP_STRING([--enable-debug], [enable debug]),\n    [CFLAGS=\"$CFLAGS -DCW_DEBUGGING\"], [])\n\nAC_ARG_ENABLE([dtls],\n    AS_HELP_STRING([--disable-dtls], [disable DTLS support]))\n\nAM_CONDITIONAL([USE_SSL], [test \"x$enable_dtls\" != \"xno\"])\nAS_IF([test \"x$enable_dtls\" != \"xno\"], [\n  AX_CHECK_OPENSSL([], [AC_MSG_ERROR(OpenSSL not found!)])\n], [\n  CFLAGS=\"$CFLAGS -DCW_NO_DTLS -DCW_NO_DTLSCWParseConfigurationUpdateRequest\"\n])\nAC_CONFIG_FILES([Makefile])\nAC_OUTPUT"
  },
  {
    "path": "debian-install.sh",
    "content": "#!/bin/sh\nautoreconf -fi\nCFLAGS=\"-Os -pipe -fno-caller-saves -DCW_NO_DTLS -DWRITE_STD_OUTPUT -DCW_DEBUGGING -DNETUDP -DAC -fgnu89-inline\" ./configure\nmake\ncp AC /usr/sbin/AC\nmkdir /etc/capwap\ncp -f config.ac /etc/capwap\ncp -f settings.ac.txt /etc/capwap\ncd hostapd_wrapper/hostapd2\n./linux-ac.sh\n"
  },
  {
    "path": "hostapd_wrapper/README.rst",
    "content": "===================\nWRAPPER FOR HOSTAPD\n===================\n\nRequirements\n------------\n\n* patch\n* hostapd-1.1\n\nInstall\n-------\n\n* copy content of src to hostapd-1.1/src\n* apply hostapd-capwap.patch\n\nSample\n------\n\n  cp hostapd-1.1\n  cp -a ../opencapwap.git/hostapd_wrapper/src .\n  patch -p1 < ../opencapwap.git/hostapd_wrapper/hostapd-capwap.patch\n\nBuild\n-----\n\nYou can either the build the AC wrapper or the WTP wrapper, but not both\nat the same time!\n\nCheck hostapd's build instructions on how to configure and build it.\n\nAdjust hostapd-1.1/hostapd/.config and enable either CONFIG_DRIVER_CAPWAP_WTP or\nCONFIG_DRIVER_CAPWAP\n\nRunning WTP\n-----------\n\n* copy hostapd_wtp.conf to /etc/hostapd\n* copy hostapd.conf-wtp to /etc/hostapd/hostapd.conf\n* adjust above files for your setup\n* create an AP interface, e.g.: /usr/sbin/iw phy phy0 interface add wlan0 type managed\n* start WTP deamon *first*\n* start hostapd\n\nRunning AP\n-----------\n\n* copy hostapd_ap.conf to /etc/hostapd\n* copy hostapd.conf-ap to /etc/hostapd/hostapd.conf\n* adjust above files for your setup\n* start AP deamon *first*\n* start hostapd\n\nKnown Problems\n--------------\n\nThe communication protocol between WTP/AC and hostapd is not stable. It does\nnot detect communication failures and therefor has no reconnect behavior.\nA WTP/AC restart always requires a hostapd restart as well. It also does not\nhandle delayed connects (i.e. hostapd started before WTP/AC is ready). Therefore\nmake sure the WTP/AC deamons are always started before hostapd.\n\nThe WTP does not handle AC connection lost and AC restart. The WTP needs to be\nrestarted to recover from such a situation.\n\n"
  },
  {
    "path": "hostapd_wrapper/hostapd-capwap.patch",
    "content": "diff --git a/hostapd/Makefile b/hostapd/Makefile\nindex e46561e..b027b43 100644\n--- a/hostapd/Makefile\n+++ b/hostapd/Makefile\n@@ -765,6 +765,10 @@ ifdef CONFIG_DEBUG_FILE\n CFLAGS += -DCONFIG_DEBUG_FILE\n endif\n \n+ifdef CONFIG_DRIVER_CAPWAP_WTP\n+CFLAGS += -DCONFIG_DRIVER_CAPWAP_WTP\n+endif\n+\n ALL=hostapd hostapd_cli\n \n all: verify_config $(ALL)\ndiff --git a/src/Makefile b/src/Makefile\nindex d73a175..7c09a0d 100644\n--- a/src/Makefile\n+++ b/src/Makefile\n@@ -1,4 +1,4 @@\n-SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps\n+SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps capwap\n \n all:\n \tfor d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done\ndiff --git a/src/ap/ap_config.h b/src/ap/ap_config.h\nindex fe20fc2..3c65570 100644\n--- a/src/ap/ap_config.h\n+++ b/src/ap/ap_config.h\n@@ -361,6 +361,9 @@ struct hostapd_bss_config {\n \t/* IEEE 802.11u - Roaming Consortium list */\n \tunsigned int roaming_consortium_count;\n \tstruct hostapd_roaming_consortium *roaming_consortium;\n+#ifdef CONFIG_DRIVER_CAPWAP_WTP\n+\tint mac_mode;\n+#endif\n };\n \n \ndiff --git a/src/ap/beacon.c b/src/ap/beacon.c\nindex 63b708a..bdba1da 100644\n--- a/src/ap/beacon.c\n+++ b/src/ap/beacon.c\n@@ -621,6 +621,9 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)\n \t    !is_zero_ether_addr(hapd->conf->hessid))\n \t\tparams.hessid = hapd->conf->hessid;\n \tparams.access_network_type = hapd->conf->access_network_type;\n+#ifdef CONFIG_DRIVER_CAPWAP_WTP\n+\tparams.mac_mode = hapd->conf->mac_mode;\n+#endif\n \tif (hostapd_drv_set_ap(hapd, &params))\n \t\twpa_printf(MSG_ERROR, \"Failed to set beacon parameters\");\n \thostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);\ndiff --git a/src/drivers/driver.h b/src/drivers/driver.h\nindex c7b7363..a22a6c6 100644\n--- a/src/drivers/driver.h\n+++ b/src/drivers/driver.h\n@@ -672,6 +672,13 @@ struct wpa_driver_ap_params {\n \t * enabled.\n \t */\n \tu8 access_network_type;\n+\n+#ifdef CONFIG_DRIVER_CAPWAP_WTP\n+\t/**\n+\t * CAPWAP MAC Mode\n+\t */\n+\tint mac_mode;\n+#endif\n };\n \n /**\ndiff --git a/src/drivers/drivers.c b/src/drivers/drivers.c\nindex b710778..e8f9c26 100644\n--- a/src/drivers/drivers.c\n+++ b/src/drivers/drivers.c\n@@ -21,6 +21,12 @@ extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */\n #ifdef CONFIG_DRIVER_NL80211\n extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */\n #endif /* CONFIG_DRIVER_NL80211 */\n+#ifdef CONFIG_DRIVER_CAPWAP_WTP\n+extern struct wpa_driver_ops wpa_driver_capwap_wtp_ops; /* driver_capwap_wtp.c */\n+#endif /* CONFIG_DRIVER_CAPWAP_WTP */\n+#ifdef CONFIG_DRIVER_CAPWAP\n+extern struct wpa_driver_ops wpa_driver_capwap_ops; /* driver_capwap.c */\n+#endif /* CONFIG_DRIVER_CAPWAP */\n #ifdef CONFIG_DRIVER_HOSTAP\n extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */\n #endif /* CONFIG_DRIVER_HOSTAP */\n@@ -71,6 +77,12 @@ struct wpa_driver_ops *wpa_drivers[] =\n #ifdef CONFIG_DRIVER_NL80211\n \t&wpa_driver_nl80211_ops,\n #endif /* CONFIG_DRIVER_NL80211 */\n+#ifdef CONFIG_DRIVER_CAPWAP_WTP\n+\t&wpa_driver_capwap_wtp_ops,\n+#endif /* CONFIG_DRIVER_CAPWAP_WTP */\n+#ifdef CONFIG_DRIVER_CAPWAP\n+\t&wpa_driver_capwap_ops,\n+#endif /* CONFIG_DRIVER_CAPWAP */\n #ifdef CONFIG_DRIVER_HOSTAP\n \t&wpa_driver_hostap_ops,\n #endif /* CONFIG_DRIVER_HOSTAP */\ndiff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak\nindex b1f70e0..eca1c7f 100644\n--- a/src/drivers/drivers.mak\n+++ b/src/drivers/drivers.mak\n@@ -38,7 +38,7 @@ endif\n ifdef CONFIG_DRIVER_NL80211\n DRV_CFLAGS += -DCONFIG_DRIVER_NL80211\n DRV_OBJS += ../src/drivers/driver_nl80211.o\n-DRV_OBJS += ../src/utils/radiotap.o\n+NEED_RADIOTAP=y\n NEED_SME=y\n NEED_AP_MLME=y\n NEED_NETLINK=y\n@@ -156,18 +156,110 @@ DRV_WPA_OBJS += ../src/drivers/driver_wext.o\n NEED_RFKILL=y\n endif\n \n+ifdef CONFIG_DRIVER_CAPWAP_WTP\n+DRV_CFLAGS += -DCONFIG_DRIVER_CAPWAP_WTP\n+DRV_OBJS += ../src/drivers/driver_capwap_wtp.o\n+NEED_RADIOTAP=y\n+NEED_SME=y\n+NEED_AP_MLME=y\n+NEED_NETLINK=y\n+NEED_LINUX_IOCTL=y\n+NEED_CAPWAP_MGMT_FRAME_WTP=y\n+NEED_CAPWAP_IPC_WTP=y\n+NEED_SWITCH_8023=y\n+NEED_RFKILL=y\n+\n+ifdef CONFIG_LIBNL32\n+  DRV_LIBS += -lnl-3\n+  DRV_LIBS += -lnl-genl-3\n+  DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3\n+else\n+  ifdef CONFIG_LIBNL_TINY\n+    DRV_LIBS += -lnl-tiny\n+  else\n+    DRV_LIBS += -lnl\n+  endif\n+\n+  ifdef CONFIG_LIBNL20\n+    DRV_LIBS += -lnl-genl\n+    DRV_CFLAGS += -DCONFIG_LIBNL20\n+  endif\n+endif\n+endif\n+\n+ifdef CONFIG_DRIVER_CAPWAP\n+DRV_CFLAGS += -DCONFIG_DRIVER_CAPWAP\n+DRV_OBJS += ../src/drivers/driver_capwap.o\n+NEED_RADIOTAP=y\n+NEED_SME=y\n+NEED_AP_MLME=y\n+NEED_FAKE_NETLINK=y\n+NEED_LINUX_FAKE_IOCTL=y\n+NEED_CAPWAP_MGMT_FRAME_AC=y\n+NEED_CAPWAP_IPC_AC=y\n+NEED_RFKILL=y\n+\n+ifdef CONFIG_LIBNL32\n+  DRV_LIBS += -lnl-3\n+  DRV_LIBS += -lnl-genl-3\n+  DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3\n+else\n+  ifdef CONFIG_LIBNL_TINY\n+    DRV_LIBS += -lnl-tiny\n+  else\n+    DRV_LIBS += -lnl\n+  endif\n+\n+  ifdef CONFIG_LIBNL20\n+    DRV_LIBS += -lnl-genl\n+    DRV_CFLAGS += -DCONFIG_LIBNL20\n+  endif\n+endif\n+endif\n+\n+ifdef NEED_RADIOTAP\n+DRV_OBJS += ../src/utils/radiotap.o\n+endif\n+\n ifdef NEED_NETLINK\n DRV_OBJS += ../src/drivers/netlink.o\n endif\n \n+ifdef NEED_FAKE_NETLINK\n+DRV_OBJS += ../src/drivers/netlink_fake.o\n+endif\n+\n ifdef NEED_LINUX_IOCTL\n DRV_OBJS += ../src/drivers/linux_ioctl.o\n endif\n \n+ifdef NEED_LINUX_FAKE_IOCTL\n+DRV_OBJS += ../src/drivers/linux_ioctl_fake.o\n+endif\n+\n ifdef NEED_RFKILL\n DRV_OBJS += ../src/drivers/rfkill.o\n endif\n \n+ifdef NEED_CAPWAP_MGMT_FRAME_WTP\n+DRV_OBJS += ../src/capwap/capwap_mgmt_frame_wtp.o\n+endif\n+\n+ifdef NEED_CAPWAP_MGMT_FRAME_AC\n+DRV_OBJS += ../src/capwap/capwap_mgmt_frame_ac.o\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_WTP\n+DRV_OBJS += ../src/capwap/ipc_capwap_wtp.o\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_AC\n+DRV_OBJS += ../src/capwap/ipc_capwap_ac.o\n+endif\n+\n+ifdef NEED_SWITCH_8023\n+DRV_OBJS += ../src/capwap/switch_8023_80211.o\n+endif\n \n ##### COMMON VARS\n DRV_BOTH_CFLAGS := $(DRV_CFLAGS) $(DRV_WPA_CFLAGS) $(DRV_AP_CFLAGS)\ndiff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk\nindex 2d1ad9d..d6a4c22 100644\n--- a/src/drivers/drivers.mk\n+++ b/src/drivers/drivers.mk\n@@ -38,7 +38,7 @@ endif\n ifdef CONFIG_DRIVER_NL80211\n DRV_CFLAGS += -DCONFIG_DRIVER_NL80211\n DRV_OBJS += src/drivers/driver_nl80211.c\n-DRV_OBJS += src/utils/radiotap.c\n+NEED_RADIOTAP=y\n NEED_SME=y\n NEED_AP_MLME=y\n NEED_NETLINK=y\n@@ -156,18 +156,111 @@ DRV_WPA_OBJS += src/drivers/driver_wext.c\n NEED_RFKILL=y\n endif\n \n+ifdef CONFIG_DRIVER_CAPWAP_WTP\n+DRV_CFLAGS += -DCONFIG_DRIVER_CAPWAP_WTP\n+DRV_OBJS += src/drivers/driver_capwap_wtp.c\n+NEED_RADIOTAP=y\n+NEED_SME=y\n+NEED_AP_MLME=y\n+NEED_NETLINK=y\n+NEED_LINUX_IOCTL=y\n+NEED_CAPWAP_MGMT_FRAME_WTP=y\n+NEED_CAPWAP_IPC_WTP=y\n+NEED_SWITCH_8023=y\n+NEED_RFKILL=y\n+\n+ifdef CONFIG_LIBNL32\n+  DRV_LIBS += -lnl-3\n+  DRV_LIBS += -lnl-genl-3\n+  DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3\n+else\n+  ifdef CONFIG_LIBNL_TINY\n+    DRV_LIBS += -lnl-tiny\n+  else\n+    DRV_LIBS += -lnl\n+  endif\n+\n+  ifdef CONFIG_LIBNL20\n+    DRV_LIBS += -lnl-genl\n+    DRV_CFLAGS += -DCONFIG_LIBNL20\n+  endif\n+endif\n+endif\n+\n+ifdef CONFIG_DRIVER_CAPWAP\n+DRV_CFLAGS += -DCONFIG_DRIVER_CAPWAP\n+DRV_OBJS += src/drivers/driver_capwap.c\n+NEED_RADIOTAP=y\n+NEED_SME=y\n+NEED_AP_MLME=y\n+NEED_FAKE_NETLINK=y\n+NEED_LINUX_FAKE_IOCTL=y\n+NEED_CAPWAP_MGMT_FRAME_AC=y\n+NEED_CAPWAP_IPC_AC=y\n+NEED_RFKILL=y\n+\n+ifdef CONFIG_LIBNL32\n+  DRV_LIBS += -lnl-3\n+  DRV_LIBS += -lnl-genl-3\n+  DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3\n+else\n+  ifdef CONFIG_LIBNL_TINY\n+    DRV_LIBS += -lnl-tiny\n+  else\n+    DRV_LIBS += -lnl\n+  endif\n+\n+  ifdef CONFIG_LIBNL20\n+    DRV_LIBS += -lnl-genl\n+    DRV_CFLAGS += -DCONFIG_LIBNL20\n+  endif\n+endif\n+endif\n+\n+ifdef NEED_RADIOTAP\n+DRV_OBJS += src/utils/radiotap.c\n+endif\n+\n ifdef NEED_NETLINK\n DRV_OBJS += src/drivers/netlink.c\n endif\n \n+ifdef NEED_FAKE_NETLINK\n+DRV_OBJS += src/drivers/netlink_fake.c\n+endif\n+\n ifdef NEED_LINUX_IOCTL\n DRV_OBJS += src/drivers/linux_ioctl.c\n endif\n \n+ifdef NEED_LINUX_FAKE_IOCTL\n+DRV_OBJS += src/drivers/linux_ioctl_fake.c\n+endif\n+\n ifdef NEED_RFKILL\n DRV_OBJS += src/drivers/rfkill.c\n endif\n \n+ifdef NEED_CAPWAP_MGMT_FRAME_WTP\n+DRV_OBJS += src/capwap/capwap_mgmt_frame_wtp.c\n+endif\n+\n+ifdef NEED_CAPWAP_MGMT_FRAME_AC\n+DRV_OBJS += src/capwap/capwap_mgmt_frame_ac.c\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_WTP\n+DRV_OBJS += src/capwap/ipc_capwap_wtp.c\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_AC\n+DRV_OBJS += src/capwap/ipc_capwap_ac.c\n+endif\n+\n+ifdef NEED_SWITCH_8023\n+DRV_OBJS += src/capwap/switch_8023_80211.c\n+endif\n+\n ifdef CONFIG_DRIVER_CUSTOM\n DRV_CFLAGS += -DCONFIG_DRIVER_CUSTOM\n endif\n"
  },
  {
    "path": "hostapd_wrapper/hostapd.conf-ac",
    "content": "##### hostapd configuration file ##############################################\n# Empty lines and lines starting with # are ignored\n\n# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for\n# management frames); ath0 for madwifi\ninterface=wlan0\n\n# In case of madwifi, atheros, and nl80211 driver interfaces, an additional\n# configuration parameter, bridge, may be used to notify hostapd if the\n# interface is included in a bridge. This parameter is not used with Host AP\n# driver. If the bridge parameter is not set, the drivers will automatically\n# figure out the bridge interface (assuming sysfs is enabled and mounted to\n# /sys) and this parameter may not be needed.\n#\n# For nl80211, this parameter can be used to request the AP interface to be\n# added to the bridge automatically (brctl may refuse to do this before hostapd\n# has been started to change the interface mode). If needed, the bridge\n# interface is also created.\n#bridge=br0\n\n# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd);\n# default: hostap). nl80211 is used with all Linux mac80211 drivers.\n# Use driver=none if building hostapd as a standalone RADIUS server that does\n# not control any wireless/wired driver.\n# driver=hostap\ndriver=capwap\n\n# hostapd event logger configuration\n#\n# Two output method: syslog and stdout (only usable if not forking to\n# background).\n#\n# Module bitfield (ORed bitfield of modules that will be logged; -1 = all\n# modules):\n# bit 0 (1) = IEEE 802.11\n# bit 1 (2) = IEEE 802.1X\n# bit 2 (4) = RADIUS\n# bit 3 (8) = WPA\n# bit 4 (16) = driver interface\n# bit 5 (32) = IAPP\n# bit 6 (64) = MLME\n#\n# Levels (minimum value for logged events):\n#  0 = verbose debugging\n#  1 = debugging\n#  2 = informational messages\n#  3 = notification\n#  4 = warning\n#\nlogger_syslog=-1\nlogger_syslog_level=2\nlogger_stdout=-1\nlogger_stdout_level=2\n\n# Dump file for state information (on SIGUSR1)\ndump_file=/tmp/hostapd.dump\n\n# Interface for separate control program. If this is specified, hostapd\n# will create this directory and a UNIX domain socket for listening to requests\n# from external programs (CLI/GUI, etc.) for status information and\n# configuration. The socket file will be named based on the interface name, so\n# multiple hostapd processes/interfaces can be run at the same time if more\n# than one interface is used.\n# /var/run/hostapd is the recommended directory for sockets and by default,\n# hostapd_cli will use it when trying to connect with hostapd.\nctrl_interface=/var/run/hostapd\n\n# Access control for the control interface can be configured by setting the\n# directory to allow only members of a group to use sockets. This way, it is\n# possible to run hostapd as root (since it needs to change network\n# configuration and open raw sockets) and still allow GUI/CLI components to be\n# run as non-root users. However, since the control interface can be used to\n# change the network configuration, this access needs to be protected in many\n# cases. By default, hostapd is configured to use gid 0 (root). If you\n# want to allow non-root users to use the contron interface, add a new group\n# and change this value to match with that group. Add users that should have\n# control interface access to this group.\n#\n# This variable can be a group name or gid.\n#ctrl_interface_group=wheel\nctrl_interface_group=0\n\n\n##### IEEE 802.11 related configuration #######################################\n\n# SSID to be used in IEEE 802.11 management frames\nssid=test\n\n# Country code (ISO/IEC 3166-1). Used to set regulatory domain.\n# Set as needed to indicate country in which device is operating.\n# This can limit available channels and transmit power.\n#country_code=US\n\n# Enable IEEE 802.11d. This advertises the country_code and the set of allowed\n# channels and transmit power levels based on the regulatory limits. The\n# country_code setting must be configured with the correct country for\n# IEEE 802.11d functions.\n# (default: 0 = disabled)\n#ieee80211d=1\n\n# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,\n# Default: IEEE 802.11b\nhw_mode=b\n\n# Channel number (IEEE 802.11)\n# (default: 0, i.e., not set)\n# Please note that some drivers do not use this value from hostapd and the\n# channel will need to be configured separately with iwconfig.\nchannel=1\n\n# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)\nbeacon_int=100\n\n# DTIM (delivery traffic information message) period (range 1..255):\n# number of beacons between DTIMs (1 = every beacon includes DTIM element)\n# (default: 2)\ndtim_period=2\n\n# Maximum number of stations allowed in station table. New stations will be\n# rejected after the station table is full. IEEE 802.11 has a limit of 2007\n# different association IDs, so this number should not be larger than that.\n# (default: 2007)\nmax_num_sta=255\n\n# RTS/CTS threshold; 2347 = disabled (default); range 0..2347\n# If this field is not included in hostapd.conf, hostapd will not control\n# RTS threshold and 'iwconfig wlan# rts <val>' can be used to set it.\nrts_threshold=2347\n\n# Fragmentation threshold; 2346 = disabled (default); range 256..2346\n# If this field is not included in hostapd.conf, hostapd will not control\n# fragmentation threshold and 'iwconfig wlan# frag <val>' can be used to set\n# it.\nfragm_threshold=2346\n\n# Rate configuration\n# Default is to enable all rates supported by the hardware. This configuration\n# item allows this list be filtered so that only the listed rates will be left\n# in the list. If the list is empty, all rates are used. This list can have\n# entries that are not in the list of rates the hardware supports (such entries\n# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110.\n# If this item is present, at least one rate have to be matching with the rates\n# hardware supports.\n# default: use the most common supported rate setting for the selected\n# hw_mode (i.e., this line can be removed from configuration file in most\n# cases)\n#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540\n\n# Basic rate set configuration\n# List of rates (in 100 kbps) that are included in the basic rate set.\n# If this item is not included, usually reasonable default set is used.\n#basic_rates=10 20\n#basic_rates=10 20 55 110\n#basic_rates=60 120 240\n\n# Short Preamble\n# This parameter can be used to enable optional use of short preamble for\n# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance.\n# This applies only to IEEE 802.11b-compatible networks and this should only be\n# enabled if the local hardware supports use of short preamble. If any of the\n# associated STAs do not support short preamble, use of short preamble will be\n# disabled (and enabled when such STAs disassociate) dynamically.\n# 0 = do not allow use of short preamble (default)\n# 1 = allow use of short preamble\n#preamble=1\n\n# Station MAC address -based authentication\n# Please note that this kind of access control requires a driver that uses\n# hostapd to take care of management frame processing and as such, this can be\n# used with driver=hostap or driver=nl80211, but not with driver=madwifi.\n# 0 = accept unless in deny list\n# 1 = deny unless in accept list\n# 2 = use external RADIUS server (accept/deny lists are searched first)\nmacaddr_acl=0\n\n# Accept/deny lists are read from separate files (containing list of\n# MAC addresses, one per line). Use absolute path name to make sure that the\n# files can be read on SIGHUP configuration reloads.\n#accept_mac_file=/etc/hostapd.accept\n#deny_mac_file=/etc/hostapd.deny\n\n# IEEE 802.11 specifies two authentication algorithms. hostapd can be\n# configured to allow both of these or only one. Open system authentication\n# should be used with IEEE 802.1X.\n# Bit fields of allowed authentication algorithms:\n# bit 0 = Open System Authentication\n# bit 1 = Shared Key Authentication (requires WEP)\nauth_algs=3\n\n# Send empty SSID in beacons and ignore probe request frames that do not\n# specify full SSID, i.e., require stations to know SSID.\n# default: disabled (0)\n# 1 = send empty (length=0) SSID in beacon and ignore probe request for\n#     broadcast SSID\n# 2 = clear SSID (ASCII 0), but keep the original length (this may be required\n#     with some clients that do not support empty SSID) and ignore probe\n#     requests for broadcast SSID\nignore_broadcast_ssid=0\n\n# TX queue parameters (EDCF / bursting)\n# tx_queue_<queue name>_<param>\n# queues: data0, data1, data2, data3, after_beacon, beacon\n#\t\t(data0 is the highest priority queue)\n# parameters:\n#   aifs: AIFS (default 2)\n#   cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023)\n#   cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin\n#   burst: maximum length (in milliseconds with precision of up to 0.1 ms) for\n#          bursting\n#\n# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):\n# These parameters are used by the access point when transmitting frames\n# to the clients.\n#\n# Low priority / AC_BK = background\n#tx_queue_data3_aifs=7\n#tx_queue_data3_cwmin=15\n#tx_queue_data3_cwmax=1023\n#tx_queue_data3_burst=0\n# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0\n#\n# Normal priority / AC_BE = best effort\n#tx_queue_data2_aifs=3\n#tx_queue_data2_cwmin=15\n#tx_queue_data2_cwmax=63\n#tx_queue_data2_burst=0\n# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0\n#\n# High priority / AC_VI = video\n#tx_queue_data1_aifs=1\n#tx_queue_data1_cwmin=7\n#tx_queue_data1_cwmax=15\n#tx_queue_data1_burst=3.0\n# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0\n#\n# Highest priority / AC_VO = voice\n#tx_queue_data0_aifs=1\n#tx_queue_data0_cwmin=3\n#tx_queue_data0_cwmax=7\n#tx_queue_data0_burst=1.5\n# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3\n\n# 802.1D Tag (= UP) to AC mappings\n# WMM specifies following mapping of data frames to different ACs. This mapping\n# can be configured using Linux QoS/tc and sch_pktpri.o module.\n# 802.1D Tag\t802.1D Designation\tAccess Category\tWMM Designation\n# 1\t\tBK\t\t\tAC_BK\t\tBackground\n# 2\t\t-\t\t\tAC_BK\t\tBackground\n# 0\t\tBE\t\t\tAC_BE\t\tBest Effort\n# 3\t\tEE\t\t\tAC_BE\t\tBest Effort\n# 4\t\tCL\t\t\tAC_VI\t\tVideo\n# 5\t\tVI\t\t\tAC_VI\t\tVideo\n# 6\t\tVO\t\t\tAC_VO\t\tVoice\n# 7\t\tNC\t\t\tAC_VO\t\tVoice\n# Data frames with no priority information: AC_BE\n# Management frames: AC_VO\n# PS-Poll frames: AC_BE\n\n# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):\n# for 802.11a or 802.11g networks\n# These parameters are sent to WMM clients when they associate.\n# The parameters will be used by WMM clients for frames transmitted to the\n# access point.\n#\n# note - txop_limit is in units of 32microseconds\n# note - acm is admission control mandatory flag. 0 = admission control not\n# required, 1 = mandatory\n# note - here cwMin and cmMax are in exponent form. the actual cw value used\n# will be (2^n)-1 where n is the value given here\n#\nwmm_enabled=1\n#\n# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD]\n# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver)\n#uapsd_advertisement_enabled=1\n#\n# Low priority / AC_BK = background\nwmm_ac_bk_cwmin=4\nwmm_ac_bk_cwmax=10\nwmm_ac_bk_aifs=7\nwmm_ac_bk_txop_limit=0\nwmm_ac_bk_acm=0\n# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10\n#\n# Normal priority / AC_BE = best effort\nwmm_ac_be_aifs=3\nwmm_ac_be_cwmin=4\nwmm_ac_be_cwmax=10\nwmm_ac_be_txop_limit=0\nwmm_ac_be_acm=0\n# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7\n#\n# High priority / AC_VI = video\nwmm_ac_vi_aifs=2\nwmm_ac_vi_cwmin=3\nwmm_ac_vi_cwmax=4\nwmm_ac_vi_txop_limit=94\nwmm_ac_vi_acm=0\n# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188\n#\n# Highest priority / AC_VO = voice\nwmm_ac_vo_aifs=2\nwmm_ac_vo_cwmin=2\nwmm_ac_vo_cwmax=3\nwmm_ac_vo_txop_limit=47\nwmm_ac_vo_acm=0\n# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102\n\n# Static WEP key configuration\n#\n# The key number to use when transmitting.\n# It must be between 0 and 3, and the corresponding key must be set.\n# default: not set\n#wep_default_key=0\n# The WEP keys to use.\n# A key may be a quoted string or unquoted hexadecimal digits.\n# The key length should be 5, 13, or 16 characters, or 10, 26, or 32\n# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or\n# 128-bit (152-bit) WEP is used.\n# Only the default key must be supplied; the others are optional.\n# default: not set\n#wep_key0=123456789a\n#wep_key1=\"vwxyz\"\n#wep_key2=0102030405060708090a0b0c0d\n#wep_key3=\".2.4.6.8.0.23\"\n\n# Station inactivity limit\n#\n# If a station does not send anything in ap_max_inactivity seconds, an\n# empty data frame is sent to it in order to verify whether it is\n# still in range. If this frame is not ACKed, the station will be\n# disassociated and then deauthenticated. This feature is used to\n# clear station table of old entries when the STAs move out of the\n# range.\n#\n# The station can associate again with the AP if it is still in range;\n# this inactivity poll is just used as a nicer way of verifying\n# inactivity; i.e., client will not report broken connection because\n# disassociation frame is not sent immediately without first polling\n# the STA with a data frame.\n# default: 300 (i.e., 5 minutes)\n#ap_max_inactivity=300\n\n# Disassociate stations based on excessive transmission failures or other\n# indications of connection loss. This depends on the driver capabilities and\n# may not be available with all drivers.\n#disassoc_low_ack=1\n\n# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to\n# remain asleep). Default: 65535 (no limit apart from field size)\n#max_listen_interval=100\n\n# WDS (4-address frame) mode with per-station virtual interfaces\n# (only supported with driver=nl80211)\n# This mode allows associated stations to use 4-address frames to allow layer 2\n# bridging to be used.\n#wds_sta=1\n\n# If bridge parameter is set, the WDS STA interface will be added to the same\n# bridge by default. This can be overridden with the wds_bridge parameter to\n# use a separate bridge.\n#wds_bridge=wds-br0\n\n# Client isolation can be used to prevent low-level bridging of frames between\n# associated stations in the BSS. By default, this bridging is allowed.\n#ap_isolate=1\n\n##### IEEE 802.11n related configuration ######################################\n\n# ieee80211n: Whether IEEE 802.11n (HT) is enabled\n# 0 = disabled (default)\n# 1 = enabled\n# Note: You will also need to enable WMM for full HT functionality.\n#ieee80211n=1\n\n# ht_capab: HT capabilities (list of flags)\n# LDPC coding capability: [LDPC] = supported\n# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary\n#\tchannel below the primary channel; [HT40+] = both 20 MHz and 40 MHz\n#\twith secondary channel below the primary channel\n#\t(20 MHz only if neither is set)\n#\tNote: There are limits on which channels can be used with HT40- and\n#\tHT40+. Following table shows the channels that may be available for\n#\tHT40- and HT40+ use per IEEE 802.11n Annex J:\n#\tfreq\t\tHT40-\t\tHT40+\n#\t2.4 GHz\t\t5-13\t\t1-7 (1-9 in Europe/Japan)\n#\t5 GHz\t\t40,48,56,64\t36,44,52,60\n#\t(depending on the location, not all of these channels may be available\n#\tfor use)\n#\tPlease note that 40 MHz channels may switch their primary and secondary\n#\tchannels if needed or creation of 40 MHz channel maybe rejected based\n#\ton overlapping BSSes. These changes are done automatically when hostapd\n#\tis setting up the 40 MHz channel.\n# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]\n#\t(SMPS disabled if neither is set)\n# HT-greenfield: [GF] (disabled if not set)\n# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)\n# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)\n# Tx STBC: [TX-STBC] (disabled if not set)\n# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial\n#\tstreams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC\n#\tdisabled if none of these set\n# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set)\n# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not\n#\tset)\n# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)\n# PSMP support: [PSMP] (disabled if not set)\n# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)\n#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]\n\n# Require stations to support HT PHY (reject association if they do not)\n#require_ht=1\n\n##### IEEE 802.1X-2004 related configuration ##################################\n\n# Require IEEE 802.1X authorization\n#ieee8021x=1\n\n# IEEE 802.1X/EAPOL version\n# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL\n# version 2. However, there are many client implementations that do not handle\n# the new version number correctly (they seem to drop the frames completely).\n# In order to make hostapd interoperate with these clients, the version number\n# can be set to the older version (1) with this configuration value.\n#eapol_version=2\n\n# Optional displayable message sent with EAP Request-Identity. The first \\0\n# in this string will be converted to ASCII-0 (nul). This can be used to\n# separate network info (comma separated list of attribute=value pairs); see,\n# e.g., RFC 4284.\n#eap_message=hello\n#eap_message=hello\\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com\n\n# WEP rekeying (disabled if key lengths are not set or are set to 0)\n# Key lengths for default/broadcast and individual/unicast keys:\n# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits)\n# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits)\n#wep_key_len_broadcast=5\n#wep_key_len_unicast=5\n# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once)\n#wep_rekey_period=300\n\n# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if\n# only broadcast keys are used)\neapol_key_index_workaround=0\n\n# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable\n# reauthentication).\n#eap_reauth_period=3600\n\n# Use PAE group address (01:80:c2:00:00:03) instead of individual target\n# address when sending EAPOL frames with driver=wired. This is the most common\n# mechanism used in wired authentication, but it also requires that the port\n# is only used by one station.\n#use_pae_group_addr=1\n\n##### Integrated EAP server ###################################################\n\n# Optionally, hostapd can be configured to use an integrated EAP server\n# to process EAP authentication locally without need for an external RADIUS\n# server. This functionality can be used both as a local authentication server\n# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices.\n\n# Use integrated EAP server instead of external RADIUS authentication\n# server. This is also needed if hostapd is configured to act as a RADIUS\n# authentication server.\neap_server=0\n\n# Path for EAP server user database\n#eap_user_file=/etc/hostapd.eap_user\n\n# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS\n#ca_cert=/etc/hostapd.ca.pem\n\n# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS\n#server_cert=/etc/hostapd.server.pem\n\n# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS\n# This may point to the same file as server_cert if both certificate and key\n# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be\n# used by commenting out server_cert and specifying the PFX file as the\n# private_key.\n#private_key=/etc/hostapd.server.prv\n\n# Passphrase for private key\n#private_key_passwd=secret passphrase\n\n# Enable CRL verification.\n# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a\n# valid CRL signed by the CA is required to be included in the ca_cert file.\n# This can be done by using PEM format for CA certificate and CRL and\n# concatenating these into one file. Whenever CRL changes, hostapd needs to be\n# restarted to take the new CRL into use.\n# 0 = do not verify CRLs (default)\n# 1 = check the CRL of the user certificate\n# 2 = check all CRLs in the certificate path\n#check_crl=1\n\n# dh_file: File path to DH/DSA parameters file (in PEM format)\n# This is an optional configuration file for setting parameters for an\n# ephemeral DH key exchange. In most cases, the default RSA authentication does\n# not use this configuration. However, it is possible setup RSA to use\n# ephemeral DH key exchange. In addition, ciphers with DSA keys always use\n# ephemeral DH keys. This can be used to achieve forward secrecy. If the file\n# is in DSA parameters format, it will be automatically converted into DH\n# params. This parameter is required if anonymous EAP-FAST is used.\n# You can generate DH parameters file with OpenSSL, e.g.,\n# \"openssl dhparam -out /etc/hostapd.dh.pem 1024\"\n#dh_file=/etc/hostapd.dh.pem\n\n# Fragment size for EAP methods\n#fragment_size=1400\n\n# Configuration data for EAP-SIM database/authentication gateway interface.\n# This is a text string in implementation specific format. The example\n# implementation in eap_sim_db.c uses this as the UNIX domain socket name for\n# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses \"unix:\"\n# prefix.\n#eap_sim_db=unix:/tmp/hlr_auc_gw.sock\n\n# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,\n# random value. It is configured as a 16-octet value in hex format. It can be\n# generated, e.g., with the following command:\n# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' '\n#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f\n\n# EAP-FAST authority identity (A-ID)\n# A-ID indicates the identity of the authority that issues PACs. The A-ID\n# should be unique across all issuing servers. In theory, this is a variable\n# length field, but due to some existing implementations requiring A-ID to be\n# 16 octets in length, it is strongly recommended to use that length for the\n# field to provid interoperability with deployed peer implementations. This\n# field is configured in hex format.\n#eap_fast_a_id=101112131415161718191a1b1c1d1e1f\n\n# EAP-FAST authority identifier information (A-ID-Info)\n# This is a user-friendly name for the A-ID. For example, the enterprise name\n# and server name in a human-readable format. This field is encoded as UTF-8.\n#eap_fast_a_id_info=test server\n\n# Enable/disable different EAP-FAST provisioning modes:\n#0 = provisioning disabled\n#1 = only anonymous provisioning allowed\n#2 = only authenticated provisioning allowed\n#3 = both provisioning modes allowed (default)\n#eap_fast_prov=3\n\n# EAP-FAST PAC-Key lifetime in seconds (hard limit)\n#pac_key_lifetime=604800\n\n# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard\n# limit). The server will generate a new PAC-Key when this number of seconds\n# (or fewer) of the lifetime remains.\n#pac_key_refresh_time=86400\n\n# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND\n# (default: 0 = disabled).\n#eap_sim_aka_result_ind=1\n\n# Trusted Network Connect (TNC)\n# If enabled, TNC validation will be required before the peer is allowed to\n# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other\n# EAP method is enabled, the peer will be allowed to connect without TNC.\n#tnc=1\n\n\n##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################\n\n# Interface to be used for IAPP broadcast packets\n#iapp_interface=eth0\n\n\n##### RADIUS client configuration #############################################\n# for IEEE 802.1X with external Authentication Server, IEEE 802.11\n# authentication with external ACL for MAC addresses, and accounting\n\n# The own IP address of the access point (used as NAS-IP-Address)\nown_ip_addr=127.0.0.1\n\n# Optional NAS-Identifier string for RADIUS messages. When used, this should be\n# a unique to the NAS within the scope of the RADIUS server. For example, a\n# fully qualified domain name can be used here.\n# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and\n# 48 octets long.\n#nas_identifier=ap.example.com\n\n# RADIUS authentication server\n#auth_server_addr=127.0.0.1\n#auth_server_port=1812\n#auth_server_shared_secret=secret\n\n# RADIUS accounting server\n#acct_server_addr=127.0.0.1\n#acct_server_port=1813\n#acct_server_shared_secret=secret\n\n# Secondary RADIUS servers; to be used if primary one does not reply to\n# RADIUS packets. These are optional and there can be more than one secondary\n# server listed.\n#auth_server_addr=127.0.0.2\n#auth_server_port=1812\n#auth_server_shared_secret=secret2\n#\n#acct_server_addr=127.0.0.2\n#acct_server_port=1813\n#acct_server_shared_secret=secret2\n\n# Retry interval for trying to return to the primary RADIUS server (in\n# seconds). RADIUS client code will automatically try to use the next server\n# when the current server is not replying to requests. If this interval is set,\n# primary server will be retried after configured amount of time even if the\n# currently used secondary server is still working.\n#radius_retry_primary_interval=600\n\n\n# Interim accounting update interval\n# If this is set (larger than 0) and acct_server is configured, hostapd will\n# send interim accounting updates every N seconds. Note: if set, this overrides\n# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this\n# value should not be configured in hostapd.conf, if RADIUS server is used to\n# control the interim interval.\n# This value should not be less 600 (10 minutes) and must not be less than\n# 60 (1 minute).\n#radius_acct_interim_interval=600\n\n# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN\n# is used for the stations. This information is parsed from following RADIUS\n# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),\n# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value\n# VLANID as a string). vlan_file option below must be configured if dynamic\n# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be\n# used to set static client MAC address to VLAN ID mapping.\n# 0 = disabled (default)\n# 1 = option; use default interface if RADIUS server does not include VLAN ID\n# 2 = required; reject authentication if RADIUS server does not include VLAN ID\n#dynamic_vlan=0\n\n# VLAN interface list for dynamic VLAN mode is read from a separate text file.\n# This list is used to map VLAN ID from the RADIUS server to a network\n# interface. Each station is bound to one interface in the same way as with\n# multiple BSSIDs or SSIDs. Each line in this text file is defining a new\n# interface and the line must include VLAN ID and interface name separated by\n# white space (space or tab).\n#vlan_file=/etc/hostapd.vlan\n\n# Interface where 802.1q tagged packets should appear when a RADIUS server is\n# used to determine which VLAN a station is on.  hostapd creates a bridge for\n# each VLAN.  Then hostapd adds a VLAN interface (associated with the interface\n# indicated by 'vlan_tagged_interface') and the appropriate wireless interface\n# to the bridge.\n#vlan_tagged_interface=eth0\n\n\n##### RADIUS authentication server configuration ##############################\n\n# hostapd can be used as a RADIUS authentication server for other hosts. This\n# requires that the integrated EAP server is also enabled and both\n# authentication services are sharing the same configuration.\n\n# File name of the RADIUS clients configuration for the RADIUS server. If this\n# commented out, RADIUS server is disabled.\n#radius_server_clients=/etc/hostapd.radius_clients\n\n# The UDP port number for the RADIUS authentication server\n#radius_server_auth_port=1812\n\n# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API)\n#radius_server_ipv6=1\n\n\n##### WPA/IEEE 802.11i configuration ##########################################\n\n# Enable WPA. Setting this variable configures the AP to require WPA (either\n# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either\n# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.\n# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),\n# RADIUS authentication server must be configured, and WPA-EAP must be included\n# in wpa_key_mgmt.\n# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)\n# and/or WPA2 (full IEEE 802.11i/RSN):\n# bit0 = WPA\n# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)\n#wpa=1\n\n# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit\n# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase\n# (8..63 characters) that will be converted to PSK. This conversion uses SSID\n# so the PSK changes when ASCII passphrase is used and the SSID is changed.\n# wpa_psk (dot11RSNAConfigPSKValue)\n# wpa_passphrase (dot11RSNAConfigPSKPassPhrase)\n#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n#wpa_passphrase=secret passphrase\n\n# Optionally, WPA PSKs can be read from a separate text file (containing list\n# of (PSK,MAC address) pairs. This allows more than one PSK to be configured.\n# Use absolute path name to make sure that the files can be read on SIGHUP\n# configuration reloads.\n#wpa_psk_file=/etc/hostapd.wpa_psk\n\n# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The\n# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be\n# added to enable SHA256-based stronger algorithms.\n# (dot11RSNAConfigAuthenticationSuitesTable)\n#wpa_key_mgmt=WPA-PSK WPA-EAP\n\n# Set of accepted cipher suites (encryption algorithms) for pairwise keys\n# (unicast packets). This is a space separated list of algorithms:\n# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]\n# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]\n# Group cipher suite (encryption algorithm for broadcast and multicast frames)\n# is automatically selected based on this configuration. If only CCMP is\n# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,\n# TKIP will be used as the group cipher.\n# (dot11RSNAConfigPairwiseCiphersTable)\n# Pairwise cipher for WPA (v1) (default: TKIP)\n#wpa_pairwise=TKIP CCMP\n# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)\n#rsn_pairwise=CCMP\n\n# Time interval for rekeying GTK (broadcast/multicast encryption keys) in\n# seconds. (dot11RSNAConfigGroupRekeyTime)\n#wpa_group_rekey=600\n\n# Rekey GTK when any STA that possesses the current GTK is leaving the BSS.\n# (dot11RSNAConfigGroupRekeyStrict)\n#wpa_strict_rekey=1\n\n# Time interval for rekeying GMK (master key used internally to generate GTKs\n# (in seconds).\n#wpa_gmk_rekey=86400\n\n# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of\n# PTK to mitigate some attacks against TKIP deficiencies.\n#wpa_ptk_rekey=600\n\n# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up\n# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN\n# authentication and key handshake before actually associating with a new AP.\n# (dot11RSNAPreauthenticationEnabled)\n#rsn_preauth=1\n#\n# Space separated list of interfaces from which pre-authentication frames are\n# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all\n# interface that are used for connections to other APs. This could include\n# wired interfaces and WDS links. The normal wireless data interface towards\n# associated stations (e.g., wlan0) should not be added, since\n# pre-authentication is only used with APs other than the currently associated\n# one.\n#rsn_preauth_interfaces=eth0\n\n# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is\n# allowed. This is only used with RSN/WPA2.\n# 0 = disabled (default)\n# 1 = enabled\n#peerkey=1\n\n# ieee80211w: Whether management frame protection (MFP) is enabled\n# 0 = disabled (default)\n# 1 = optional\n# 2 = required\n#ieee80211w=0\n\n# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)\n# (maximum time to wait for a SA Query response)\n# dot11AssociationSAQueryMaximumTimeout, 1...4294967295\n#assoc_sa_query_max_timeout=1000\n\n# Association SA Query retry timeout (in TU = 1.024 ms; for MFP)\n# (time between two subsequent SA Query requests)\n# dot11AssociationSAQueryRetryTimeout, 1...4294967295\n#assoc_sa_query_retry_timeout=201\n\n# disable_pmksa_caching: Disable PMKSA caching\n# This parameter can be used to disable caching of PMKSA created through EAP\n# authentication. RSN preauthentication may still end up using PMKSA caching if\n# it is enabled (rsn_preauth=1).\n# 0 = PMKSA caching enabled (default)\n# 1 = PMKSA caching disabled\n#disable_pmksa_caching=0\n\n# okc: Opportunistic Key Caching (aka Proactive Key Caching)\n# Allow PMK cache to be shared opportunistically among configured interfaces\n# and BSSes (i.e., all configurations within a single hostapd process).\n# 0 = disabled (default)\n# 1 = enabled\n#okc=1\n\n\n##### IEEE 802.11r configuration ##############################################\n\n# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)\n# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the\n# same SSID) between which a STA can use Fast BSS Transition.\n# 2-octet identifier as a hex string.\n#mobility_domain=a1b2\n\n# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID)\n# 1 to 48 octet identifier.\n# This is configured with nas_identifier (see RADIUS client section above).\n\n# Default lifetime of the PMK-RO in minutes; range 1..65535\n# (dot11FTR0KeyLifetime)\n#r0_key_lifetime=10000\n\n# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID)\n# 6-octet identifier as a hex string.\n#r1_key_holder=000102030405\n\n# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535)\n# (dot11FTReassociationDeadline)\n#reassociation_deadline=1000\n\n# List of R0KHs in the same Mobility Domain\n# format: <MAC address> <NAS Identifier> <128-bit key as hex string>\n# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC\n# address when requesting PMK-R1 key from the R0KH that the STA used during the\n# Initial Mobility Domain Association.\n#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f\n#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff\n# And so on.. One line per R0KH.\n\n# List of R1KHs in the same Mobility Domain\n# format: <MAC address> <R1KH-ID> <128-bit key as hex string>\n# This list is used to map R1KH-ID to a destination MAC address when sending\n# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD\n# that can request PMK-R1 keys.\n#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f\n#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff\n# And so on.. One line per R1KH.\n\n# Whether PMK-R1 push is enabled at R0KH\n# 0 = do not push PMK-R1 to all configured R1KHs (default)\n# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived\n#pmk_r1_push=1\n\n##### Neighbor table ##########################################################\n# Maximum number of entries kept in AP table (either for neigbor table or for\n# detecting Overlapping Legacy BSS Condition). The oldest entry will be\n# removed when adding a new entry that would make the list grow over this\n# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is\n# enabled, so this field should not be set to 0 when using IEEE 802.11g.\n# default: 255\n#ap_table_max_size=255\n\n# Number of seconds of no frames received after which entries may be deleted\n# from the AP table. Since passive scanning is not usually performed frequently\n# this should not be set to very small value. In addition, there is no\n# guarantee that every scan cycle will receive beacon frames from the\n# neighboring APs.\n# default: 60\n#ap_table_expiration_time=3600\n\n\n##### Wi-Fi Protected Setup (WPS) #############################################\n\n# WPS state\n# 0 = WPS disabled (default)\n# 1 = WPS enabled, not configured\n# 2 = WPS enabled, configured\n#wps_state=2\n\n# AP can be configured into a locked state where new WPS Registrar are not\n# accepted, but previously authorized Registrars (including the internal one)\n# can continue to add new Enrollees.\n#ap_setup_locked=1\n\n# Universally Unique IDentifier (UUID; see RFC 4122) of the device\n# This value is used as the UUID for the internal WPS Registrar. If the AP\n# is also using UPnP, this value should be set to the device's UPnP UUID.\n# If not configured, UUID will be generated based on the local MAC address.\n#uuid=12345678-9abc-def0-1234-56789abcdef0\n\n# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs\n# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the\n# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of\n# per-device PSKs is recommended as the more secure option (i.e., make sure to\n# set wpa_psk_file when using WPS with WPA-PSK).\n\n# When an Enrollee requests access to the network with PIN method, the Enrollee\n# PIN will need to be entered for the Registrar. PIN request notifications are\n# sent to hostapd ctrl_iface monitor. In addition, they can be written to a\n# text file that could be used, e.g., to populate the AP administration UI with\n# pending PIN requests. If the following variable is set, the PIN requests will\n# be written to the configured file.\n#wps_pin_requests=/var/run/hostapd_wps_pin_requests\n\n# Device Name\n# User-friendly description of device; up to 32 octets encoded in UTF-8\n#device_name=Wireless AP\n\n# Manufacturer\n# The manufacturer of the device (up to 64 ASCII characters)\n#manufacturer=Company\n\n# Model Name\n# Model of the device (up to 32 ASCII characters)\n#model_name=WAP\n\n# Model Number\n# Additional device description (up to 32 ASCII characters)\n#model_number=123\n\n# Serial Number\n# Serial number of the device (up to 32 characters)\n#serial_number=12345\n\n# Primary Device Type\n# Used format: <categ>-<OUI>-<subcateg>\n# categ = Category as an integer value\n# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for\n#       default WPS OUI\n# subcateg = OUI-specific Sub Category as an integer value\n# Examples:\n#   1-0050F204-1 (Computer / PC)\n#   1-0050F204-2 (Computer / Server)\n#   5-0050F204-1 (Storage / NAS)\n#   6-0050F204-1 (Network Infrastructure / AP)\n#device_type=6-0050F204-1\n\n# OS Version\n# 4-octet operating system version number (hex string)\n#os_version=01020300\n\n# Config Methods\n# List of the supported configuration methods\n# Available methods: usba ethernet label display ext_nfc_token int_nfc_token\n#\tnfc_interface push_button keypad virtual_display physical_display\n#\tvirtual_push_button physical_push_button\n#config_methods=label virtual_display virtual_push_button keypad\n\n# WPS capability discovery workaround for PBC with Windows 7\n# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting\n# as a Registrar and using M1 from the AP. The config methods attribute in that\n# message is supposed to indicate only the configuration method supported by\n# the AP in Enrollee role, i.e., to add an external Registrar. For that case,\n# PBC shall not be used and as such, the PushButton config method is removed\n# from M1 by default. If pbc_in_m1=1 is included in the configuration file,\n# the PushButton config method is left in M1 (if included in config_methods\n# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label\n# in the AP).\n#pbc_in_m1=1\n\n# Static access point PIN for initial configuration and adding Registrars\n# If not set, hostapd will not allow external WPS Registrars to control the\n# access point. The AP PIN can also be set at runtime with hostapd_cli\n# wps_ap_pin command. Use of temporary (enabled by user action) and random\n# AP PIN is much more secure than configuring a static AP PIN here. As such,\n# use of the ap_pin parameter is not recommended if the AP device has means for\n# displaying a random PIN.\n#ap_pin=12345670\n\n# Skip building of automatic WPS credential\n# This can be used to allow the automatically generated Credential attribute to\n# be replaced with pre-configured Credential(s).\n#skip_cred_build=1\n\n# Additional Credential attribute(s)\n# This option can be used to add pre-configured Credential attributes into M8\n# message when acting as a Registrar. If skip_cred_build=1, this data will also\n# be able to override the Credential attribute that would have otherwise been\n# automatically generated based on network configuration. This configuration\n# option points to an external file that much contain the WPS Credential\n# attribute(s) as binary data.\n#extra_cred=hostapd.cred\n\n# Credential processing\n#   0 = process received credentials internally (default)\n#   1 = do not process received credentials; just pass them over ctrl_iface to\n#\texternal program(s)\n#   2 = process received credentials internally and pass them over ctrl_iface\n#\tto external program(s)\n# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and\n# extra_cred be used to provide the Credential data for Enrollees.\n#\n# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file\n# both for Credential processing and for marking AP Setup Locked based on\n# validation failures of AP PIN. An external program is responsible on updating\n# the configuration appropriately in this case.\n#wps_cred_processing=0\n\n# AP Settings Attributes for M7\n# By default, hostapd generates the AP Settings Attributes for M7 based on the\n# current configuration. It is possible to override this by providing a file\n# with pre-configured attributes. This is similar to extra_cred file format,\n# but the AP Settings attributes are not encapsulated in a Credential\n# attribute.\n#ap_settings=hostapd.ap_settings\n\n# WPS UPnP interface\n# If set, support for external Registrars is enabled.\n#upnp_iface=br0\n\n# Friendly Name (required for UPnP)\n# Short description for end use. Should be less than 64 characters.\n#friendly_name=WPS Access Point\n\n# Manufacturer URL (optional for UPnP)\n#manufacturer_url=http://www.example.com/\n\n# Model Description (recommended for UPnP)\n# Long description for end user. Should be less than 128 characters.\n#model_description=Wireless Access Point\n\n# Model URL (optional for UPnP)\n#model_url=http://www.example.com/model/\n\n# Universal Product Code (optional for UPnP)\n# 12-digit, all-numeric code that identifies the consumer package.\n#upc=123456789012\n\n##### Wi-Fi Direct (P2P) ######################################################\n\n# Enable P2P Device management\n#manage_p2p=1\n\n# Allow cross connection\n#allow_cross_connection=1\n\n#### TDLS (IEEE 802.11z-2010) #################################################\n\n# Prohibit use of TDLS in this BSS\n#tdls_prohibit=1\n\n# Prohibit use of TDLS Channel Switching in this BSS\n#tdls_prohibit_chan_switch=1\n\n##### IEEE 802.11v-2011 #######################################################\n\n# Time advertisement\n# 0 = disabled (default)\n# 2 = UTC time at which the TSF timer is 0\n#time_advertisement=2\n\n# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:\n# stdoffset[dst[offset][,start[/time],end[/time]]]\n#time_zone=EST5\n\n##### IEEE 802.11u-2011 #######################################################\n\n# Enable Interworking service\n#interworking=1\n\n# Access Network Type\n# 0 = Private network\n# 1 = Private network with guest access\n# 2 = Chargeable public network\n# 3 = Free public network\n# 4 = Personal device network\n# 5 = Emergency services only network\n# 14 = Test or experimental\n# 15 = Wildcard\n#access_network_type=0\n\n# Whether the network provides connectivity to the Internet\n# 0 = Unspecified\n# 1 = Network provides connectivity to the Internet\n#internet=1\n\n# Additional Step Required for Access\n# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if\n# RSN is used.\n#asra=0\n\n# Emergency services reachable\n#esr=0\n\n# Unauthenticated emergency service accessible\n#uesa=0\n\n# Venue Info (optional)\n# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.\n# Example values (group,type):\n# 0,0 = Unspecified\n# 1,7 = Convention Center\n# 1,13 = Coffee Shop\n# 2,0 = Unspecified Business\n# 7,1  Private Residence\n#venue_group=7\n#venue_type=1\n\n# Homogeneous ESS identifier (optional; dot11HESSID)\n# If set, this shall be identifical to one of the BSSIDs in the homogeneous\n# ESS and this shall be set to the same value across all BSSs in homogeneous\n# ESS.\n#hessid=02:03:04:05:06:07\n\n# Roaming Consortium List\n# Arbitrary number of Roaming Consortium OIs can be configured with each line\n# adding a new OI to the list. The first three entries are available through\n# Beacon and Probe Response frames. Any additional entry will be available only\n# through ANQP queries. Each OI is between 3 and 15 octets and is configured a\n# a hexstring.\n#roaming_consortium=021122\n#roaming_consortium=2233445566\n\n##### Multiple BSSID support ##################################################\n#\n# Above configuration is using the default interface (wlan#, or multi-SSID VLAN\n# interfaces). Other BSSIDs can be added by using separator 'bss' with\n# default interface name to be allocated for the data packets of the new BSS.\n#\n# hostapd will generate BSSID mask based on the BSSIDs that are\n# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is\n# not the case, the MAC address of the radio must be changed before starting\n# hostapd (ifconfig wlan0 hw ether <MAC addr>). If a BSSID is configured for\n# every secondary BSS, this limitation is not applied at hostapd and other\n# masks may be used if the driver supports them (e.g., swap the locally\n# administered bit)\n#\n# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is\n# specified using the 'bssid' parameter.\n# If an explicit BSSID is specified, it must be chosen such that it:\n# - results in a valid MASK that covers it and the dev_addr\n# - is not the same as the MAC address of the radio\n# - is not the same as any other explicitly specified BSSID\n#\n# Please note that hostapd uses some of the values configured for the first BSS\n# as the defaults for the following BSSes. However, it is recommended that all\n# BSSes include explicit configuration of all relevant configuration items.\n#\n#bss=wlan0_0\n#ssid=test2\n# most of the above items can be used here (apart from radio interface specific\n# items, like channel)\n\n#bss=wlan0_1\n#bssid=00:13:10:95:fe:0b\n# ...\n"
  },
  {
    "path": "hostapd_wrapper/hostapd.conf-wtp",
    "content": "##### hostapd configuration file ##############################################\n# Empty lines and lines starting with # are ignored\n\n# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for\n# management frames); ath0 for madwifi\ninterface=wlan0\n\n# In case of madwifi, atheros, and nl80211 driver interfaces, an additional\n# configuration parameter, bridge, may be used to notify hostapd if the\n# interface is included in a bridge. This parameter is not used with Host AP\n# driver. If the bridge parameter is not set, the drivers will automatically\n# figure out the bridge interface (assuming sysfs is enabled and mounted to\n# /sys) and this parameter may not be needed.\n#\n# For nl80211, this parameter can be used to request the AP interface to be\n# added to the bridge automatically (brctl may refuse to do this before hostapd\n# has been started to change the interface mode). If needed, the bridge\n# interface is also created.\n#bridge=br0\n\n# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd);\n# default: hostap). nl80211 is used with all Linux mac80211 drivers.\n# Use driver=none if building hostapd as a standalone RADIUS server that does\n# not control any wireless/wired driver.\n# driver=hostap\ndriver=capwap_wtp\n\n# hostapd event logger configuration\n#\n# Two output method: syslog and stdout (only usable if not forking to\n# background).\n#\n# Module bitfield (ORed bitfield of modules that will be logged; -1 = all\n# modules):\n# bit 0 (1) = IEEE 802.11\n# bit 1 (2) = IEEE 802.1X\n# bit 2 (4) = RADIUS\n# bit 3 (8) = WPA\n# bit 4 (16) = driver interface\n# bit 5 (32) = IAPP\n# bit 6 (64) = MLME\n#\n# Levels (minimum value for logged events):\n#  0 = verbose debugging\n#  1 = debugging\n#  2 = informational messages\n#  3 = notification\n#  4 = warning\n#\nlogger_syslog=-1\nlogger_syslog_level=2\nlogger_stdout=-1\nlogger_stdout_level=2\n\n# Dump file for state information (on SIGUSR1)\ndump_file=/tmp/hostapd.dump\n\n# Interface for separate control program. If this is specified, hostapd\n# will create this directory and a UNIX domain socket for listening to requests\n# from external programs (CLI/GUI, etc.) for status information and\n# configuration. The socket file will be named based on the interface name, so\n# multiple hostapd processes/interfaces can be run at the same time if more\n# than one interface is used.\n# /var/run/hostapd is the recommended directory for sockets and by default,\n# hostapd_cli will use it when trying to connect with hostapd.\nctrl_interface=/var/run/hostapd\n\n# Access control for the control interface can be configured by setting the\n# directory to allow only members of a group to use sockets. This way, it is\n# possible to run hostapd as root (since it needs to change network\n# configuration and open raw sockets) and still allow GUI/CLI components to be\n# run as non-root users. However, since the control interface can be used to\n# change the network configuration, this access needs to be protected in many\n# cases. By default, hostapd is configured to use gid 0 (root). If you\n# want to allow non-root users to use the contron interface, add a new group\n# and change this value to match with that group. Add users that should have\n# control interface access to this group.\n#\n# This variable can be a group name or gid.\n#ctrl_interface_group=wheel\nctrl_interface_group=0\n\n\n##### IEEE 802.11 related configuration #######################################\n\n# SSID to be used in IEEE 802.11 management frames\nssid=test\n\n# Country code (ISO/IEC 3166-1). Used to set regulatory domain.\n# Set as needed to indicate country in which device is operating.\n# This can limit available channels and transmit power.\n#country_code=US\n\n# Enable IEEE 802.11d. This advertises the country_code and the set of allowed\n# channels and transmit power levels based on the regulatory limits. The\n# country_code setting must be configured with the correct country for\n# IEEE 802.11d functions.\n# (default: 0 = disabled)\n#ieee80211d=1\n\n# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,\n# Default: IEEE 802.11b\nhw_mode=g\n\n# Channel number (IEEE 802.11)\n# (default: 0, i.e., not set)\n# Please note that some drivers do not use this value from hostapd and the\n# channel will need to be configured separately with iwconfig.\nchannel=1\n\n# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)\nbeacon_int=100\n\n# DTIM (delivery traffic information message) period (range 1..255):\n# number of beacons between DTIMs (1 = every beacon includes DTIM element)\n# (default: 2)\ndtim_period=2\n\n# Maximum number of stations allowed in station table. New stations will be\n# rejected after the station table is full. IEEE 802.11 has a limit of 2007\n# different association IDs, so this number should not be larger than that.\n# (default: 2007)\nmax_num_sta=255\n\n# RTS/CTS threshold; 2347 = disabled (default); range 0..2347\n# If this field is not included in hostapd.conf, hostapd will not control\n# RTS threshold and 'iwconfig wlan# rts <val>' can be used to set it.\nrts_threshold=2347\n\n# Fragmentation threshold; 2346 = disabled (default); range 256..2346\n# If this field is not included in hostapd.conf, hostapd will not control\n# fragmentation threshold and 'iwconfig wlan# frag <val>' can be used to set\n# it.\nfragm_threshold=2346\n\n# Rate configuration\n# Default is to enable all rates supported by the hardware. This configuration\n# item allows this list be filtered so that only the listed rates will be left\n# in the list. If the list is empty, all rates are used. This list can have\n# entries that are not in the list of rates the hardware supports (such entries\n# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110.\n# If this item is present, at least one rate have to be matching with the rates\n# hardware supports.\n# default: use the most common supported rate setting for the selected\n# hw_mode (i.e., this line can be removed from configuration file in most\n# cases)\n#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540\n\n# Basic rate set configuration\n# List of rates (in 100 kbps) that are included in the basic rate set.\n# If this item is not included, usually reasonable default set is used.\n#basic_rates=10 20\n#basic_rates=10 20 55 110\n#basic_rates=60 120 240\n\n# Short Preamble\n# This parameter can be used to enable optional use of short preamble for\n# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance.\n# This applies only to IEEE 802.11b-compatible networks and this should only be\n# enabled if the local hardware supports use of short preamble. If any of the\n# associated STAs do not support short preamble, use of short preamble will be\n# disabled (and enabled when such STAs disassociate) dynamically.\n# 0 = do not allow use of short preamble (default)\n# 1 = allow use of short preamble\n#preamble=1\n\n# Station MAC address -based authentication\n# Please note that this kind of access control requires a driver that uses\n# hostapd to take care of management frame processing and as such, this can be\n# used with driver=hostap or driver=nl80211, but not with driver=madwifi.\n# 0 = accept unless in deny list\n# 1 = deny unless in accept list\n# 2 = use external RADIUS server (accept/deny lists are searched first)\nmacaddr_acl=0\n\n# Accept/deny lists are read from separate files (containing list of\n# MAC addresses, one per line). Use absolute path name to make sure that the\n# files can be read on SIGHUP configuration reloads.\n#accept_mac_file=/etc/hostapd.accept\n#deny_mac_file=/etc/hostapd.deny\n\n# IEEE 802.11 specifies two authentication algorithms. hostapd can be\n# configured to allow both of these or only one. Open system authentication\n# should be used with IEEE 802.1X.\n# Bit fields of allowed authentication algorithms:\n# bit 0 = Open System Authentication\n# bit 1 = Shared Key Authentication (requires WEP)\nauth_algs=3\n\n# Send empty SSID in beacons and ignore probe request frames that do not\n# specify full SSID, i.e., require stations to know SSID.\n# default: disabled (0)\n# 1 = send empty (length=0) SSID in beacon and ignore probe request for\n#     broadcast SSID\n# 2 = clear SSID (ASCII 0), but keep the original length (this may be required\n#     with some clients that do not support empty SSID) and ignore probe\n#     requests for broadcast SSID\nignore_broadcast_ssid=0\n\n# TX queue parameters (EDCF / bursting)\n# tx_queue_<queue name>_<param>\n# queues: data0, data1, data2, data3, after_beacon, beacon\n#\t\t(data0 is the highest priority queue)\n# parameters:\n#   aifs: AIFS (default 2)\n#   cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023)\n#   cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin\n#   burst: maximum length (in milliseconds with precision of up to 0.1 ms) for\n#          bursting\n#\n# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):\n# These parameters are used by the access point when transmitting frames\n# to the clients.\n#\n# Low priority / AC_BK = background\n#tx_queue_data3_aifs=7\n#tx_queue_data3_cwmin=15\n#tx_queue_data3_cwmax=1023\n#tx_queue_data3_burst=0\n# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0\n#\n# Normal priority / AC_BE = best effort\n#tx_queue_data2_aifs=3\n#tx_queue_data2_cwmin=15\n#tx_queue_data2_cwmax=63\n#tx_queue_data2_burst=0\n# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0\n#\n# High priority / AC_VI = video\n#tx_queue_data1_aifs=1\n#tx_queue_data1_cwmin=7\n#tx_queue_data1_cwmax=15\n#tx_queue_data1_burst=3.0\n# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0\n#\n# Highest priority / AC_VO = voice\n#tx_queue_data0_aifs=1\n#tx_queue_data0_cwmin=3\n#tx_queue_data0_cwmax=7\n#tx_queue_data0_burst=1.5\n# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3\n\n# 802.1D Tag (= UP) to AC mappings\n# WMM specifies following mapping of data frames to different ACs. This mapping\n# can be configured using Linux QoS/tc and sch_pktpri.o module.\n# 802.1D Tag\t802.1D Designation\tAccess Category\tWMM Designation\n# 1\t\tBK\t\t\tAC_BK\t\tBackground\n# 2\t\t-\t\t\tAC_BK\t\tBackground\n# 0\t\tBE\t\t\tAC_BE\t\tBest Effort\n# 3\t\tEE\t\t\tAC_BE\t\tBest Effort\n# 4\t\tCL\t\t\tAC_VI\t\tVideo\n# 5\t\tVI\t\t\tAC_VI\t\tVideo\n# 6\t\tVO\t\t\tAC_VO\t\tVoice\n# 7\t\tNC\t\t\tAC_VO\t\tVoice\n# Data frames with no priority information: AC_BE\n# Management frames: AC_VO\n# PS-Poll frames: AC_BE\n\n# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):\n# for 802.11a or 802.11g networks\n# These parameters are sent to WMM clients when they associate.\n# The parameters will be used by WMM clients for frames transmitted to the\n# access point.\n#\n# note - txop_limit is in units of 32microseconds\n# note - acm is admission control mandatory flag. 0 = admission control not\n# required, 1 = mandatory\n# note - here cwMin and cmMax are in exponent form. the actual cw value used\n# will be (2^n)-1 where n is the value given here\n#\nwmm_enabled=1\n#\n# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD]\n# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver)\n#uapsd_advertisement_enabled=1\n#\n# Low priority / AC_BK = background\nwmm_ac_bk_cwmin=4\nwmm_ac_bk_cwmax=10\nwmm_ac_bk_aifs=7\nwmm_ac_bk_txop_limit=0\nwmm_ac_bk_acm=0\n# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10\n#\n# Normal priority / AC_BE = best effort\nwmm_ac_be_aifs=3\nwmm_ac_be_cwmin=4\nwmm_ac_be_cwmax=10\nwmm_ac_be_txop_limit=0\nwmm_ac_be_acm=0\n# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7\n#\n# High priority / AC_VI = video\nwmm_ac_vi_aifs=2\nwmm_ac_vi_cwmin=3\nwmm_ac_vi_cwmax=4\nwmm_ac_vi_txop_limit=94\nwmm_ac_vi_acm=0\n# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188\n#\n# Highest priority / AC_VO = voice\nwmm_ac_vo_aifs=2\nwmm_ac_vo_cwmin=2\nwmm_ac_vo_cwmax=3\nwmm_ac_vo_txop_limit=47\nwmm_ac_vo_acm=0\n# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102\n\n# Static WEP key configuration\n#\n# The key number to use when transmitting.\n# It must be between 0 and 3, and the corresponding key must be set.\n# default: not set\n#wep_default_key=0\n# The WEP keys to use.\n# A key may be a quoted string or unquoted hexadecimal digits.\n# The key length should be 5, 13, or 16 characters, or 10, 26, or 32\n# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or\n# 128-bit (152-bit) WEP is used.\n# Only the default key must be supplied; the others are optional.\n# default: not set\n#wep_key0=123456789a\n#wep_key1=\"vwxyz\"\n#wep_key2=0102030405060708090a0b0c0d\n#wep_key3=\".2.4.6.8.0.23\"\n\n# Station inactivity limit\n#\n# If a station does not send anything in ap_max_inactivity seconds, an\n# empty data frame is sent to it in order to verify whether it is\n# still in range. If this frame is not ACKed, the station will be\n# disassociated and then deauthenticated. This feature is used to\n# clear station table of old entries when the STAs move out of the\n# range.\n#\n# The station can associate again with the AP if it is still in range;\n# this inactivity poll is just used as a nicer way of verifying\n# inactivity; i.e., client will not report broken connection because\n# disassociation frame is not sent immediately without first polling\n# the STA with a data frame.\n# default: 300 (i.e., 5 minutes)\n#ap_max_inactivity=300\n\n# Disassociate stations based on excessive transmission failures or other\n# indications of connection loss. This depends on the driver capabilities and\n# may not be available with all drivers.\n#disassoc_low_ack=1\n\n# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to\n# remain asleep). Default: 65535 (no limit apart from field size)\n#max_listen_interval=100\n\n# WDS (4-address frame) mode with per-station virtual interfaces\n# (only supported with driver=nl80211)\n# This mode allows associated stations to use 4-address frames to allow layer 2\n# bridging to be used.\n#wds_sta=1\n\n# If bridge parameter is set, the WDS STA interface will be added to the same\n# bridge by default. This can be overridden with the wds_bridge parameter to\n# use a separate bridge.\n#wds_bridge=wds-br0\n\n# Client isolation can be used to prevent low-level bridging of frames between\n# associated stations in the BSS. By default, this bridging is allowed.\n#ap_isolate=1\n\n##### IEEE 802.11n related configuration ######################################\n\n# ieee80211n: Whether IEEE 802.11n (HT) is enabled\n# 0 = disabled (default)\n# 1 = enabled\n# Note: You will also need to enable WMM for full HT functionality.\n#ieee80211n=1\n\n# ht_capab: HT capabilities (list of flags)\n# LDPC coding capability: [LDPC] = supported\n# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary\n#\tchannel below the primary channel; [HT40+] = both 20 MHz and 40 MHz\n#\twith secondary channel below the primary channel\n#\t(20 MHz only if neither is set)\n#\tNote: There are limits on which channels can be used with HT40- and\n#\tHT40+. Following table shows the channels that may be available for\n#\tHT40- and HT40+ use per IEEE 802.11n Annex J:\n#\tfreq\t\tHT40-\t\tHT40+\n#\t2.4 GHz\t\t5-13\t\t1-7 (1-9 in Europe/Japan)\n#\t5 GHz\t\t40,48,56,64\t36,44,52,60\n#\t(depending on the location, not all of these channels may be available\n#\tfor use)\n#\tPlease note that 40 MHz channels may switch their primary and secondary\n#\tchannels if needed or creation of 40 MHz channel maybe rejected based\n#\ton overlapping BSSes. These changes are done automatically when hostapd\n#\tis setting up the 40 MHz channel.\n# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]\n#\t(SMPS disabled if neither is set)\n# HT-greenfield: [GF] (disabled if not set)\n# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)\n# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)\n# Tx STBC: [TX-STBC] (disabled if not set)\n# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial\n#\tstreams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC\n#\tdisabled if none of these set\n# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set)\n# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not\n#\tset)\n# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)\n# PSMP support: [PSMP] (disabled if not set)\n# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)\n#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]\n\n# Require stations to support HT PHY (reject association if they do not)\n#require_ht=1\n\n##### IEEE 802.1X-2004 related configuration ##################################\n\n# Require IEEE 802.1X authorization\n#ieee8021x=1\n\n# IEEE 802.1X/EAPOL version\n# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL\n# version 2. However, there are many client implementations that do not handle\n# the new version number correctly (they seem to drop the frames completely).\n# In order to make hostapd interoperate with these clients, the version number\n# can be set to the older version (1) with this configuration value.\n#eapol_version=2\n\n# Optional displayable message sent with EAP Request-Identity. The first \\0\n# in this string will be converted to ASCII-0 (nul). This can be used to\n# separate network info (comma separated list of attribute=value pairs); see,\n# e.g., RFC 4284.\n#eap_message=hello\n#eap_message=hello\\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com\n\n# WEP rekeying (disabled if key lengths are not set or are set to 0)\n# Key lengths for default/broadcast and individual/unicast keys:\n# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits)\n# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits)\n#wep_key_len_broadcast=5\n#wep_key_len_unicast=5\n# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once)\n#wep_rekey_period=300\n\n# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if\n# only broadcast keys are used)\neapol_key_index_workaround=0\n\n# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable\n# reauthentication).\n#eap_reauth_period=3600\n\n# Use PAE group address (01:80:c2:00:00:03) instead of individual target\n# address when sending EAPOL frames with driver=wired. This is the most common\n# mechanism used in wired authentication, but it also requires that the port\n# is only used by one station.\n#use_pae_group_addr=1\n\n##### Integrated EAP server ###################################################\n\n# Optionally, hostapd can be configured to use an integrated EAP server\n# to process EAP authentication locally without need for an external RADIUS\n# server. This functionality can be used both as a local authentication server\n# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices.\n\n# Use integrated EAP server instead of external RADIUS authentication\n# server. This is also needed if hostapd is configured to act as a RADIUS\n# authentication server.\neap_server=0\n\n# Path for EAP server user database\n#eap_user_file=/etc/hostapd.eap_user\n\n# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS\n#ca_cert=/etc/hostapd.ca.pem\n\n# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS\n#server_cert=/etc/hostapd.server.pem\n\n# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS\n# This may point to the same file as server_cert if both certificate and key\n# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be\n# used by commenting out server_cert and specifying the PFX file as the\n# private_key.\n#private_key=/etc/hostapd.server.prv\n\n# Passphrase for private key\n#private_key_passwd=secret passphrase\n\n# Enable CRL verification.\n# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a\n# valid CRL signed by the CA is required to be included in the ca_cert file.\n# This can be done by using PEM format for CA certificate and CRL and\n# concatenating these into one file. Whenever CRL changes, hostapd needs to be\n# restarted to take the new CRL into use.\n# 0 = do not verify CRLs (default)\n# 1 = check the CRL of the user certificate\n# 2 = check all CRLs in the certificate path\n#check_crl=1\n\n# dh_file: File path to DH/DSA parameters file (in PEM format)\n# This is an optional configuration file for setting parameters for an\n# ephemeral DH key exchange. In most cases, the default RSA authentication does\n# not use this configuration. However, it is possible setup RSA to use\n# ephemeral DH key exchange. In addition, ciphers with DSA keys always use\n# ephemeral DH keys. This can be used to achieve forward secrecy. If the file\n# is in DSA parameters format, it will be automatically converted into DH\n# params. This parameter is required if anonymous EAP-FAST is used.\n# You can generate DH parameters file with OpenSSL, e.g.,\n# \"openssl dhparam -out /etc/hostapd.dh.pem 1024\"\n#dh_file=/etc/hostapd.dh.pem\n\n# Fragment size for EAP methods\n#fragment_size=1400\n\n# Configuration data for EAP-SIM database/authentication gateway interface.\n# This is a text string in implementation specific format. The example\n# implementation in eap_sim_db.c uses this as the UNIX domain socket name for\n# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses \"unix:\"\n# prefix.\n#eap_sim_db=unix:/tmp/hlr_auc_gw.sock\n\n# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,\n# random value. It is configured as a 16-octet value in hex format. It can be\n# generated, e.g., with the following command:\n# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' '\n#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f\n\n# EAP-FAST authority identity (A-ID)\n# A-ID indicates the identity of the authority that issues PACs. The A-ID\n# should be unique across all issuing servers. In theory, this is a variable\n# length field, but due to some existing implementations requiring A-ID to be\n# 16 octets in length, it is strongly recommended to use that length for the\n# field to provid interoperability with deployed peer implementations. This\n# field is configured in hex format.\n#eap_fast_a_id=101112131415161718191a1b1c1d1e1f\n\n# EAP-FAST authority identifier information (A-ID-Info)\n# This is a user-friendly name for the A-ID. For example, the enterprise name\n# and server name in a human-readable format. This field is encoded as UTF-8.\n#eap_fast_a_id_info=test server\n\n# Enable/disable different EAP-FAST provisioning modes:\n#0 = provisioning disabled\n#1 = only anonymous provisioning allowed\n#2 = only authenticated provisioning allowed\n#3 = both provisioning modes allowed (default)\n#eap_fast_prov=3\n\n# EAP-FAST PAC-Key lifetime in seconds (hard limit)\n#pac_key_lifetime=604800\n\n# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard\n# limit). The server will generate a new PAC-Key when this number of seconds\n# (or fewer) of the lifetime remains.\n#pac_key_refresh_time=86400\n\n# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND\n# (default: 0 = disabled).\n#eap_sim_aka_result_ind=1\n\n# Trusted Network Connect (TNC)\n# If enabled, TNC validation will be required before the peer is allowed to\n# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other\n# EAP method is enabled, the peer will be allowed to connect without TNC.\n#tnc=1\n\n\n##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################\n\n# Interface to be used for IAPP broadcast packets\n#iapp_interface=eth0\n\n\n##### RADIUS client configuration #############################################\n# for IEEE 802.1X with external Authentication Server, IEEE 802.11\n# authentication with external ACL for MAC addresses, and accounting\n\n# The own IP address of the access point (used as NAS-IP-Address)\nown_ip_addr=127.0.0.1\n\n# Optional NAS-Identifier string for RADIUS messages. When used, this should be\n# a unique to the NAS within the scope of the RADIUS server. For example, a\n# fully qualified domain name can be used here.\n# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and\n# 48 octets long.\n#nas_identifier=ap.example.com\n\n# RADIUS authentication server\n#auth_server_addr=127.0.0.1\n#auth_server_port=1812\n#auth_server_shared_secret=secret\n\n# RADIUS accounting server\n#acct_server_addr=127.0.0.1\n#acct_server_port=1813\n#acct_server_shared_secret=secret\n\n# Secondary RADIUS servers; to be used if primary one does not reply to\n# RADIUS packets. These are optional and there can be more than one secondary\n# server listed.\n#auth_server_addr=127.0.0.2\n#auth_server_port=1812\n#auth_server_shared_secret=secret2\n#\n#acct_server_addr=127.0.0.2\n#acct_server_port=1813\n#acct_server_shared_secret=secret2\n\n# Retry interval for trying to return to the primary RADIUS server (in\n# seconds). RADIUS client code will automatically try to use the next server\n# when the current server is not replying to requests. If this interval is set,\n# primary server will be retried after configured amount of time even if the\n# currently used secondary server is still working.\n#radius_retry_primary_interval=600\n\n\n# Interim accounting update interval\n# If this is set (larger than 0) and acct_server is configured, hostapd will\n# send interim accounting updates every N seconds. Note: if set, this overrides\n# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this\n# value should not be configured in hostapd.conf, if RADIUS server is used to\n# control the interim interval.\n# This value should not be less 600 (10 minutes) and must not be less than\n# 60 (1 minute).\n#radius_acct_interim_interval=600\n\n# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN\n# is used for the stations. This information is parsed from following RADIUS\n# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),\n# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value\n# VLANID as a string). vlan_file option below must be configured if dynamic\n# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be\n# used to set static client MAC address to VLAN ID mapping.\n# 0 = disabled (default)\n# 1 = option; use default interface if RADIUS server does not include VLAN ID\n# 2 = required; reject authentication if RADIUS server does not include VLAN ID\n#dynamic_vlan=0\n\n# VLAN interface list for dynamic VLAN mode is read from a separate text file.\n# This list is used to map VLAN ID from the RADIUS server to a network\n# interface. Each station is bound to one interface in the same way as with\n# multiple BSSIDs or SSIDs. Each line in this text file is defining a new\n# interface and the line must include VLAN ID and interface name separated by\n# white space (space or tab).\n#vlan_file=/etc/hostapd.vlan\n\n# Interface where 802.1q tagged packets should appear when a RADIUS server is\n# used to determine which VLAN a station is on.  hostapd creates a bridge for\n# each VLAN.  Then hostapd adds a VLAN interface (associated with the interface\n# indicated by 'vlan_tagged_interface') and the appropriate wireless interface\n# to the bridge.\n#vlan_tagged_interface=eth0\n\n\n##### RADIUS authentication server configuration ##############################\n\n# hostapd can be used as a RADIUS authentication server for other hosts. This\n# requires that the integrated EAP server is also enabled and both\n# authentication services are sharing the same configuration.\n\n# File name of the RADIUS clients configuration for the RADIUS server. If this\n# commented out, RADIUS server is disabled.\n#radius_server_clients=/etc/hostapd.radius_clients\n\n# The UDP port number for the RADIUS authentication server\n#radius_server_auth_port=1812\n\n# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API)\n#radius_server_ipv6=1\n\n\n##### WPA/IEEE 802.11i configuration ##########################################\n\n# Enable WPA. Setting this variable configures the AP to require WPA (either\n# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either\n# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.\n# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),\n# RADIUS authentication server must be configured, and WPA-EAP must be included\n# in wpa_key_mgmt.\n# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)\n# and/or WPA2 (full IEEE 802.11i/RSN):\n# bit0 = WPA\n# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)\n#wpa=1\n\n# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit\n# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase\n# (8..63 characters) that will be converted to PSK. This conversion uses SSID\n# so the PSK changes when ASCII passphrase is used and the SSID is changed.\n# wpa_psk (dot11RSNAConfigPSKValue)\n# wpa_passphrase (dot11RSNAConfigPSKPassPhrase)\n#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n#wpa_passphrase=secret passphrase\n\n# Optionally, WPA PSKs can be read from a separate text file (containing list\n# of (PSK,MAC address) pairs. This allows more than one PSK to be configured.\n# Use absolute path name to make sure that the files can be read on SIGHUP\n# configuration reloads.\n#wpa_psk_file=/etc/hostapd.wpa_psk\n\n# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The\n# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be\n# added to enable SHA256-based stronger algorithms.\n# (dot11RSNAConfigAuthenticationSuitesTable)\n#wpa_key_mgmt=WPA-PSK WPA-EAP\n\n# Set of accepted cipher suites (encryption algorithms) for pairwise keys\n# (unicast packets). This is a space separated list of algorithms:\n# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]\n# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]\n# Group cipher suite (encryption algorithm for broadcast and multicast frames)\n# is automatically selected based on this configuration. If only CCMP is\n# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,\n# TKIP will be used as the group cipher.\n# (dot11RSNAConfigPairwiseCiphersTable)\n# Pairwise cipher for WPA (v1) (default: TKIP)\n#wpa_pairwise=TKIP CCMP\n# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)\n#rsn_pairwise=CCMP\n\n# Time interval for rekeying GTK (broadcast/multicast encryption keys) in\n# seconds. (dot11RSNAConfigGroupRekeyTime)\n#wpa_group_rekey=600\n\n# Rekey GTK when any STA that possesses the current GTK is leaving the BSS.\n# (dot11RSNAConfigGroupRekeyStrict)\n#wpa_strict_rekey=1\n\n# Time interval for rekeying GMK (master key used internally to generate GTKs\n# (in seconds).\n#wpa_gmk_rekey=86400\n\n# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of\n# PTK to mitigate some attacks against TKIP deficiencies.\n#wpa_ptk_rekey=600\n\n# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up\n# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN\n# authentication and key handshake before actually associating with a new AP.\n# (dot11RSNAPreauthenticationEnabled)\n#rsn_preauth=1\n#\n# Space separated list of interfaces from which pre-authentication frames are\n# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all\n# interface that are used for connections to other APs. This could include\n# wired interfaces and WDS links. The normal wireless data interface towards\n# associated stations (e.g., wlan0) should not be added, since\n# pre-authentication is only used with APs other than the currently associated\n# one.\n#rsn_preauth_interfaces=eth0\n\n# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is\n# allowed. This is only used with RSN/WPA2.\n# 0 = disabled (default)\n# 1 = enabled\n#peerkey=1\n\n# ieee80211w: Whether management frame protection (MFP) is enabled\n# 0 = disabled (default)\n# 1 = optional\n# 2 = required\n#ieee80211w=0\n\n# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)\n# (maximum time to wait for a SA Query response)\n# dot11AssociationSAQueryMaximumTimeout, 1...4294967295\n#assoc_sa_query_max_timeout=1000\n\n# Association SA Query retry timeout (in TU = 1.024 ms; for MFP)\n# (time between two subsequent SA Query requests)\n# dot11AssociationSAQueryRetryTimeout, 1...4294967295\n#assoc_sa_query_retry_timeout=201\n\n# disable_pmksa_caching: Disable PMKSA caching\n# This parameter can be used to disable caching of PMKSA created through EAP\n# authentication. RSN preauthentication may still end up using PMKSA caching if\n# it is enabled (rsn_preauth=1).\n# 0 = PMKSA caching enabled (default)\n# 1 = PMKSA caching disabled\n#disable_pmksa_caching=0\n\n# okc: Opportunistic Key Caching (aka Proactive Key Caching)\n# Allow PMK cache to be shared opportunistically among configured interfaces\n# and BSSes (i.e., all configurations within a single hostapd process).\n# 0 = disabled (default)\n# 1 = enabled\n#okc=1\n\n\n##### IEEE 802.11r configuration ##############################################\n\n# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)\n# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the\n# same SSID) between which a STA can use Fast BSS Transition.\n# 2-octet identifier as a hex string.\n#mobility_domain=a1b2\n\n# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID)\n# 1 to 48 octet identifier.\n# This is configured with nas_identifier (see RADIUS client section above).\n\n# Default lifetime of the PMK-RO in minutes; range 1..65535\n# (dot11FTR0KeyLifetime)\n#r0_key_lifetime=10000\n\n# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID)\n# 6-octet identifier as a hex string.\n#r1_key_holder=000102030405\n\n# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535)\n# (dot11FTReassociationDeadline)\n#reassociation_deadline=1000\n\n# List of R0KHs in the same Mobility Domain\n# format: <MAC address> <NAS Identifier> <128-bit key as hex string>\n# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC\n# address when requesting PMK-R1 key from the R0KH that the STA used during the\n# Initial Mobility Domain Association.\n#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f\n#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff\n# And so on.. One line per R0KH.\n\n# List of R1KHs in the same Mobility Domain\n# format: <MAC address> <R1KH-ID> <128-bit key as hex string>\n# This list is used to map R1KH-ID to a destination MAC address when sending\n# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD\n# that can request PMK-R1 keys.\n#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f\n#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff\n# And so on.. One line per R1KH.\n\n# Whether PMK-R1 push is enabled at R0KH\n# 0 = do not push PMK-R1 to all configured R1KHs (default)\n# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived\n#pmk_r1_push=1\n\n##### Neighbor table ##########################################################\n# Maximum number of entries kept in AP table (either for neigbor table or for\n# detecting Overlapping Legacy BSS Condition). The oldest entry will be\n# removed when adding a new entry that would make the list grow over this\n# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is\n# enabled, so this field should not be set to 0 when using IEEE 802.11g.\n# default: 255\n#ap_table_max_size=255\n\n# Number of seconds of no frames received after which entries may be deleted\n# from the AP table. Since passive scanning is not usually performed frequently\n# this should not be set to very small value. In addition, there is no\n# guarantee that every scan cycle will receive beacon frames from the\n# neighboring APs.\n# default: 60\n#ap_table_expiration_time=3600\n\n\n##### Wi-Fi Protected Setup (WPS) #############################################\n\n# WPS state\n# 0 = WPS disabled (default)\n# 1 = WPS enabled, not configured\n# 2 = WPS enabled, configured\n#wps_state=2\n\n# AP can be configured into a locked state where new WPS Registrar are not\n# accepted, but previously authorized Registrars (including the internal one)\n# can continue to add new Enrollees.\n#ap_setup_locked=1\n\n# Universally Unique IDentifier (UUID; see RFC 4122) of the device\n# This value is used as the UUID for the internal WPS Registrar. If the AP\n# is also using UPnP, this value should be set to the device's UPnP UUID.\n# If not configured, UUID will be generated based on the local MAC address.\n#uuid=12345678-9abc-def0-1234-56789abcdef0\n\n# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs\n# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the\n# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of\n# per-device PSKs is recommended as the more secure option (i.e., make sure to\n# set wpa_psk_file when using WPS with WPA-PSK).\n\n# When an Enrollee requests access to the network with PIN method, the Enrollee\n# PIN will need to be entered for the Registrar. PIN request notifications are\n# sent to hostapd ctrl_iface monitor. In addition, they can be written to a\n# text file that could be used, e.g., to populate the AP administration UI with\n# pending PIN requests. If the following variable is set, the PIN requests will\n# be written to the configured file.\n#wps_pin_requests=/var/run/hostapd_wps_pin_requests\n\n# Device Name\n# User-friendly description of device; up to 32 octets encoded in UTF-8\n#device_name=Wireless AP\n\n# Manufacturer\n# The manufacturer of the device (up to 64 ASCII characters)\n#manufacturer=Company\n\n# Model Name\n# Model of the device (up to 32 ASCII characters)\n#model_name=WAP\n\n# Model Number\n# Additional device description (up to 32 ASCII characters)\n#model_number=123\n\n# Serial Number\n# Serial number of the device (up to 32 characters)\n#serial_number=12345\n\n# Primary Device Type\n# Used format: <categ>-<OUI>-<subcateg>\n# categ = Category as an integer value\n# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for\n#       default WPS OUI\n# subcateg = OUI-specific Sub Category as an integer value\n# Examples:\n#   1-0050F204-1 (Computer / PC)\n#   1-0050F204-2 (Computer / Server)\n#   5-0050F204-1 (Storage / NAS)\n#   6-0050F204-1 (Network Infrastructure / AP)\n#device_type=6-0050F204-1\n\n# OS Version\n# 4-octet operating system version number (hex string)\n#os_version=01020300\n\n# Config Methods\n# List of the supported configuration methods\n# Available methods: usba ethernet label display ext_nfc_token int_nfc_token\n#\tnfc_interface push_button keypad virtual_display physical_display\n#\tvirtual_push_button physical_push_button\n#config_methods=label virtual_display virtual_push_button keypad\n\n# WPS capability discovery workaround for PBC with Windows 7\n# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting\n# as a Registrar and using M1 from the AP. The config methods attribute in that\n# message is supposed to indicate only the configuration method supported by\n# the AP in Enrollee role, i.e., to add an external Registrar. For that case,\n# PBC shall not be used and as such, the PushButton config method is removed\n# from M1 by default. If pbc_in_m1=1 is included in the configuration file,\n# the PushButton config method is left in M1 (if included in config_methods\n# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label\n# in the AP).\n#pbc_in_m1=1\n\n# Static access point PIN for initial configuration and adding Registrars\n# If not set, hostapd will not allow external WPS Registrars to control the\n# access point. The AP PIN can also be set at runtime with hostapd_cli\n# wps_ap_pin command. Use of temporary (enabled by user action) and random\n# AP PIN is much more secure than configuring a static AP PIN here. As such,\n# use of the ap_pin parameter is not recommended if the AP device has means for\n# displaying a random PIN.\n#ap_pin=12345670\n\n# Skip building of automatic WPS credential\n# This can be used to allow the automatically generated Credential attribute to\n# be replaced with pre-configured Credential(s).\n#skip_cred_build=1\n\n# Additional Credential attribute(s)\n# This option can be used to add pre-configured Credential attributes into M8\n# message when acting as a Registrar. If skip_cred_build=1, this data will also\n# be able to override the Credential attribute that would have otherwise been\n# automatically generated based on network configuration. This configuration\n# option points to an external file that much contain the WPS Credential\n# attribute(s) as binary data.\n#extra_cred=hostapd.cred\n\n# Credential processing\n#   0 = process received credentials internally (default)\n#   1 = do not process received credentials; just pass them over ctrl_iface to\n#\texternal program(s)\n#   2 = process received credentials internally and pass them over ctrl_iface\n#\tto external program(s)\n# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and\n# extra_cred be used to provide the Credential data for Enrollees.\n#\n# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file\n# both for Credential processing and for marking AP Setup Locked based on\n# validation failures of AP PIN. An external program is responsible on updating\n# the configuration appropriately in this case.\n#wps_cred_processing=0\n\n# AP Settings Attributes for M7\n# By default, hostapd generates the AP Settings Attributes for M7 based on the\n# current configuration. It is possible to override this by providing a file\n# with pre-configured attributes. This is similar to extra_cred file format,\n# but the AP Settings attributes are not encapsulated in a Credential\n# attribute.\n#ap_settings=hostapd.ap_settings\n\n# WPS UPnP interface\n# If set, support for external Registrars is enabled.\n#upnp_iface=br0\n\n# Friendly Name (required for UPnP)\n# Short description for end use. Should be less than 64 characters.\n#friendly_name=WPS Access Point\n\n# Manufacturer URL (optional for UPnP)\n#manufacturer_url=http://www.example.com/\n\n# Model Description (recommended for UPnP)\n# Long description for end user. Should be less than 128 characters.\n#model_description=Wireless Access Point\n\n# Model URL (optional for UPnP)\n#model_url=http://www.example.com/model/\n\n# Universal Product Code (optional for UPnP)\n# 12-digit, all-numeric code that identifies the consumer package.\n#upc=123456789012\n\n##### Wi-Fi Direct (P2P) ######################################################\n\n# Enable P2P Device management\n#manage_p2p=1\n\n# Allow cross connection\n#allow_cross_connection=1\n\n#### TDLS (IEEE 802.11z-2010) #################################################\n\n# Prohibit use of TDLS in this BSS\n#tdls_prohibit=1\n\n# Prohibit use of TDLS Channel Switching in this BSS\n#tdls_prohibit_chan_switch=1\n\n##### IEEE 802.11v-2011 #######################################################\n\n# Time advertisement\n# 0 = disabled (default)\n# 2 = UTC time at which the TSF timer is 0\n#time_advertisement=2\n\n# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:\n# stdoffset[dst[offset][,start[/time],end[/time]]]\n#time_zone=EST5\n\n##### IEEE 802.11u-2011 #######################################################\n\n# Enable Interworking service\n#interworking=1\n\n# Access Network Type\n# 0 = Private network\n# 1 = Private network with guest access\n# 2 = Chargeable public network\n# 3 = Free public network\n# 4 = Personal device network\n# 5 = Emergency services only network\n# 14 = Test or experimental\n# 15 = Wildcard\n#access_network_type=0\n\n# Whether the network provides connectivity to the Internet\n# 0 = Unspecified\n# 1 = Network provides connectivity to the Internet\n#internet=1\n\n# Additional Step Required for Access\n# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if\n# RSN is used.\n#asra=0\n\n# Emergency services reachable\n#esr=0\n\n# Unauthenticated emergency service accessible\n#uesa=0\n\n# Venue Info (optional)\n# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.\n# Example values (group,type):\n# 0,0 = Unspecified\n# 1,7 = Convention Center\n# 1,13 = Coffee Shop\n# 2,0 = Unspecified Business\n# 7,1  Private Residence\n#venue_group=7\n#venue_type=1\n\n# Homogeneous ESS identifier (optional; dot11HESSID)\n# If set, this shall be identifical to one of the BSSIDs in the homogeneous\n# ESS and this shall be set to the same value across all BSSs in homogeneous\n# ESS.\n#hessid=02:03:04:05:06:07\n\n# Roaming Consortium List\n# Arbitrary number of Roaming Consortium OIs can be configured with each line\n# adding a new OI to the list. The first three entries are available through\n# Beacon and Probe Response frames. Any additional entry will be available only\n# through ANQP queries. Each OI is between 3 and 15 octets and is configured a\n# a hexstring.\n#roaming_consortium=021122\n#roaming_consortium=2233445566\n\n##### Multiple BSSID support ##################################################\n#\n# Above configuration is using the default interface (wlan#, or multi-SSID VLAN\n# interfaces). Other BSSIDs can be added by using separator 'bss' with\n# default interface name to be allocated for the data packets of the new BSS.\n#\n# hostapd will generate BSSID mask based on the BSSIDs that are\n# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is\n# not the case, the MAC address of the radio must be changed before starting\n# hostapd (ifconfig wlan0 hw ether <MAC addr>). If a BSSID is configured for\n# every secondary BSS, this limitation is not applied at hostapd and other\n# masks may be used if the driver supports them (e.g., swap the locally\n# administered bit)\n#\n# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is\n# specified using the 'bssid' parameter.\n# If an explicit BSSID is specified, it must be chosen such that it:\n# - results in a valid MASK that covers it and the dev_addr\n# - is not the same as the MAC address of the radio\n# - is not the same as any other explicitly specified BSSID\n#\n# Please note that hostapd uses some of the values configured for the first BSS\n# as the defaults for the following BSSes. However, it is recommended that all\n# BSSes include explicit configuration of all relevant configuration items.\n#\n#bss=wlan0_0\n#ssid=test2\n# most of the above items can be used here (apart from radio interface specific\n# items, like channel)\n\n#bss=wlan0_1\n#bssid=00:13:10:95:fe:0b\n# ...\n"
  },
  {
    "path": "hostapd_wrapper/hostapd2/README.Debian",
    "content": "\nInstallation steps:\n\n1. Flash a firmware with the hostapd-capwap package on a OpenWRT compatible router.\n2. Setup a Debian box where you want to run AC.\n3. On the Debian box :\n\t- Run ./debian-install.sh\n\t- Edit /etc/hostapd.conf\n\t- Run AC; hostapd /etc/hostapd.conf\n4. On the OpenWRT router :\n\t- Run killall -9 hostapd\n\t- Copy /tmp/run/hostapd-phy0.conf to /etc/capwap/hostapd.conf\n\t- Edit the driver in /etc/capwap/hostapd.conf line and set it to capwap_wtp\n\t- Run cd /etc/capwap; WTP; hostapd hostapd.conf\n9. Enjoy the RX_MGMT events flowing trough the radiotap tunnel.\n\n\nNotes: \n\n- Always run AC first and WTP after.\n- When hostapd on AC is closed also the hostapd on WTP is closed.\n- When you want to restart allways kill hostapd, AC and WTP processes.\n"
  },
  {
    "path": "hostapd_wrapper/hostapd2/hostapd-20130302-linux.patch",
    "content": "diff -purN hostapd-20130302/hostapd/.config hostapd-20130302-linux/hostapd/.config\n--- hostapd-20130302/hostapd/.config\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/.config\t2013-07-06 06:07:21.000000000 -0400\n@@ -0,0 +1,169 @@\n+# Example hostapd build time configuration\n+#\n+# This file lists the configuration options that are used when building the\n+# hostapd binary. All lines starting with # are ignored. Configuration option\n+# lines must be commented out complete, if they are not to be included, i.e.,\n+# just setting VARIABLE=n is not disabling that variable.\n+#\n+# This file is included in Makefile, so variables like CFLAGS and LIBS can also\n+# be modified from here. In most cass, these lines should use += in order not\n+# to override previous values of the variables.\n+\n+# Driver interface for Host AP driver\n+CONFIG_DRIVER_HOSTAP=y\n+\n+CONFIG_LIBNL_TINY=y\n+\n+# Driver interface for wired authenticator\n+CONFIG_DRIVER_WIRED=y\n+\n+# Driver interface for madwifi driver\n+#CONFIG_DRIVER_MADWIFI=y\n+#CFLAGS += -I../../madwifi # change to the madwifi source directory\n+\n+# Driver interface for Prism54 driver\n+#CONFIG_DRIVER_PRISM54=y\n+\n+# Driver interface for drivers using the nl80211 kernel interface\n+CONFIG_DRIVER_NL80211=y\n+# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be\n+# shipped with your distribution yet. If that is the case, you need to build\n+# newer libnl version and point the hostapd build to use it.\n+#LIBNL=/usr/src/libnl\n+#CFLAGS += -I$(LIBNL)/include\n+#LIBS += -L$(LIBNL)/lib\n+\n+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)\n+#CONFIG_DRIVER_BSD=y\n+#CFLAGS += -I/usr/local/include\n+#LIBS += -L/usr/local/lib\n+\n+# Driver interface for no driver (e.g., RADIUS server only)\n+#CONFIG_DRIVER_NONE=y\n+\n+# IEEE 802.11F/IAPP\n+CONFIG_IAPP=y\n+\n+# WPA2/IEEE 802.11i RSN pre-authentication\n+CONFIG_RSN_PREAUTH=y\n+\n+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)\n+CONFIG_PEERKEY=y\n+\n+# IEEE 802.11w (management frame protection)\n+# This version is an experimental implementation based on IEEE 802.11w/D1.0\n+# draft and is subject to change since the standard has not yet been finalized.\n+# Driver support is also needed for IEEE 802.11w.\n+#CONFIG_IEEE80211W=y\n+\n+# Integrated EAP server\n+CONFIG_EAP=y\n+\n+# EAP-MD5 for the integrated EAP server\n+CONFIG_EAP_MD5=y\n+\n+# EAP-TLS for the integrated EAP server\n+CONFIG_EAP_TLS=y\n+\n+# EAP-MSCHAPv2 for the integrated EAP server\n+CONFIG_EAP_MSCHAPV2=y\n+\n+# EAP-PEAP for the integrated EAP server\n+CONFIG_EAP_PEAP=y\n+\n+# EAP-GTC for the integrated EAP server\n+CONFIG_EAP_GTC=y\n+\n+# EAP-TTLS for the integrated EAP server\n+CONFIG_EAP_TTLS=y\n+\n+# EAP-SIM for the integrated EAP server\n+#CONFIG_EAP_SIM=y\n+\n+# EAP-AKA for the integrated EAP server\n+#CONFIG_EAP_AKA=y\n+\n+# EAP-AKA' for the integrated EAP server\n+# This requires CONFIG_EAP_AKA to be enabled, too.\n+#CONFIG_EAP_AKA_PRIME=y\n+\n+# EAP-PAX for the integrated EAP server\n+#CONFIG_EAP_PAX=y\n+\n+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)\n+#CONFIG_EAP_PSK=y\n+\n+# EAP-SAKE for the integrated EAP server\n+#CONFIG_EAP_SAKE=y\n+\n+# EAP-GPSK for the integrated EAP server\n+#CONFIG_EAP_GPSK=y\n+# Include support for optional SHA256 cipher suite in EAP-GPSK\n+#CONFIG_EAP_GPSK_SHA256=y\n+\n+# EAP-FAST for the integrated EAP server\n+# Note: Default OpenSSL package does not include support for all the\n+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,\n+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)\n+# to add the needed functions.\n+#CONFIG_EAP_FAST=y\n+\n+# Wi-Fi Protected Setup (WPS)\n+#CONFIG_WPS=y\n+# Enable UPnP support for external WPS Registrars\n+#CONFIG_WPS_UPNP=y\n+\n+# EAP-IKEv2\n+#CONFIG_EAP_IKEV2=y\n+\n+# Trusted Network Connect (EAP-TNC)\n+#CONFIG_EAP_TNC=y\n+\n+# PKCS#12 (PFX) support (used to read private key and certificate file from\n+# a file that usually has extension .p12 or .pfx)\n+CONFIG_PKCS12=y\n+\n+# RADIUS authentication server. This provides access to the integrated EAP\n+# server from external hosts using RADIUS.\n+#CONFIG_RADIUS_SERVER=y\n+\n+# Build IPv6 support for RADIUS operations\n+CONFIG_IPV6=y\n+\n+# IEEE Std 802.11r-2008 (Fast BSS Transition)\n+#CONFIG_IEEE80211R=y\n+\n+# Use the hostapd's IEEE 802.11 authentication (ACL), but without\n+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)\n+#CONFIG_DRIVER_RADIUS_ACL=y\n+\n+# IEEE 802.11n (High Throughput) support\n+CONFIG_IEEE80211N=y\n+\n+# Remove debugging code that is printing out debug messages to stdout.\n+# This can be used to reduce the size of the hostapd considerably if debugging\n+# code is not needed.\n+#CONFIG_NO_STDOUT_DEBUG=y\n+\n+# Remove support for RADIUS accounting\n+#CONFIG_NO_ACCOUNTING=y\n+\n+# Remove support for RADIUS\n+#CONFIG_NO_RADIUS=y\n+\n+# Remove support for VLANs\n+#CONFIG_NO_VLAN=y\n+\n+CONFIG_TLS=internal\n+CONFIG_INTERNAL_LIBTOMMATH=y\n+CONFIG_INTERNAL_AES=y\n+NEED_AES_DEC=y\n+\n+CONFIG_NO_DUMP_STATE=y\n+\n+CONFIG_WPS=y\n+CONFIG_FULL_DYNAMIC_VLAN=y\n+\n+CONFIG_UBUS=y\n+\n+CONFIG_DRIVER_CAPWAP=y\ndiff -purN hostapd-20130302/hostapd/config_file.c hostapd-20130302-linux/hostapd/config_file.c\n--- hostapd-20130302/hostapd/config_file.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/config_file.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -2464,6 +2464,8 @@ static int hostapd_config_fill(struct ho\n \t\t\t}\n #endif /* CONFIG_IEEE80211W */\n #ifdef CONFIG_IEEE80211N\n+\t\t} else if (os_strcmp(buf, \"noscan\") == 0) {\n+\t\t\tconf->noscan = atoi(pos);\n \t\t} else if (os_strcmp(buf, \"ieee80211n\") == 0) {\n \t\t\tconf->ieee80211n = atoi(pos);\n \t\t} else if (os_strcmp(buf, \"ht_capab\") == 0) {\n@@ -2472,6 +2474,10 @@ static int hostapd_config_fill(struct ho\n \t\t\t\t\t   \"ht_capab\", line);\n \t\t\t\terrors++;\n \t\t\t}\n+\t\t} else if (os_strcmp(buf, \"dynamic_ht40\") == 0) {\n+\t\t\tconf->dynamic_ht40 = atoi(pos);\n+\t\t\tif (conf->dynamic_ht40 == 1)\n+\t\t\t\tconf->dynamic_ht40 = 1500;\n \t\t} else if (os_strcmp(buf, \"require_ht\") == 0) {\n \t\t\tconf->require_ht = atoi(pos);\n #endif /* CONFIG_IEEE80211N */\ndiff -purN hostapd-20130302/hostapd/ctrl_iface.c hostapd-20130302-linux/hostapd/ctrl_iface.c\n--- hostapd-20130302/hostapd/ctrl_iface.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/ctrl_iface.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -33,6 +33,7 @@\n #include \"wps/wps.h\"\n #include \"config_file.h\"\n #include \"ctrl_iface.h\"\n+#include \"config_file.h\"\n \n \n struct wpa_ctrl_dst {\n@@ -43,6 +44,7 @@ struct wpa_ctrl_dst {\n \tint errors;\n };\n \n+static char *reload_opts = NULL;\n \n static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,\n \t\t\t\t    const char *buf, size_t len);\n@@ -152,6 +154,68 @@ static int hostapd_ctrl_iface_new_sta(st\n \treturn 0;\n }\n \n+static int hostapd_ctrl_iface_set_down(struct hostapd_data *hapd)\n+{\n+\tif (hapd->driver->stop_ap)\n+\t\thapd->driver->stop_ap(hapd->drv_priv);\n+\treturn 0;\n+}\n+\n+static char *get_option(char *opt, char *str)\n+{\n+\tint len = strlen(str);\n+\n+\tif (!strncmp(opt, str, len))\n+\t\treturn opt + len;\n+\telse\n+\t\treturn NULL;\n+}\n+\n+static struct hostapd_config *hostapd_ctrl_iface_config_read(const char *fname)\n+{\n+\tstruct hostapd_config *conf;\n+\tchar *opt, *val;\n+\n+\tconf = hostapd_config_read(fname);\n+\tif (!conf)\n+\t\treturn NULL;\n+\n+\tfor (opt = strtok(reload_opts, \" \");\n+\t     opt;\n+\t\t opt = strtok(NULL, \" \")) {\n+\n+\t\tif ((val = get_option(opt, \"channel=\")))\n+\t\t\tconf->channel = atoi(val);\n+\t\telse if ((val = get_option(opt, \"ht_capab=\")))\n+\t\t\tconf->ht_capab = atoi(val);\n+\t\telse if ((val = get_option(opt, \"ht_capab_mask=\")))\n+\t\t\tconf->ht_capab &= atoi(val);\n+\t\telse if ((val = get_option(opt, \"sec_chan=\")))\n+\t\t\tconf->secondary_channel = atoi(val);\n+\t\telse if ((val = get_option(opt, \"hw_mode=\")))\n+\t\t\tconf->hw_mode = atoi(val);\n+\t\telse if ((val = get_option(opt, \"ieee80211n=\")))\n+\t\t\tconf->ieee80211n = atoi(val);\n+\t\telse\n+\t\t\tbreak;\n+\t}\n+\n+\treturn conf;\n+}\n+\n+static int hostapd_ctrl_iface_update(struct hostapd_data *hapd, char *txt)\n+{\n+\tstruct hostapd_config * (*config_read_cb)(const char *config_fname);\n+\tstruct hostapd_iface *iface = hapd->iface;\n+\n+\tconfig_read_cb = iface->interfaces->config_read_cb;\n+\tiface->interfaces->config_read_cb = hostapd_ctrl_iface_config_read;\n+\treload_opts = txt;\n+\n+\thostapd_reload_config(iface);\n+\n+\tiface->interfaces->config_read_cb = config_read_cb;\n+}\n \n #ifdef CONFIG_IEEE80211W\n #ifdef NEED_AP_MLME\n@@ -415,6 +479,9 @@ static int hostapd_ctrl_iface_wps_ap_pin\n \tchar *pos;\n \tconst char *pin_txt;\n \n+\tif (!hapd->wps)\n+\t\treturn -1;\n+\n \tpos = os_strchr(txt, ' ');\n \tif (pos)\n \t\t*pos++ = '\\0';\n@@ -873,6 +940,7 @@ static void hostapd_ctrl_iface_receive(i\n \t} else if (os_strncmp(buf, \"RELOG\", 5) == 0) {\n \t\tif (wpa_debug_reopen_file() < 0)\n \t\t\treply_len = -1;\n+#ifdef CONFIG_CTRL_IFACE_MIB\n \t} else if (os_strcmp(buf, \"MIB\") == 0) {\n \t\treply_len = ieee802_11_get_mib(hapd, reply, reply_size);\n \t\tif (reply_len >= 0) {\n@@ -902,6 +970,12 @@ static void hostapd_ctrl_iface_receive(i\n \t\t\t\treply_len += res;\n \t\t}\n #endif /* CONFIG_NO_RADIUS */\n+#endif\n+\t} else if (os_strcmp(buf, \"DOWN\") == 0) {\n+\t\thostapd_ctrl_iface_set_down(hapd);\n+\t} else if (os_strncmp(buf, \"UPDATE \", 7) == 0) {\n+\t\thostapd_ctrl_iface_update(hapd, buf + 7);\n+#ifdef CONFIG_CTRL_IFACE_MIB\n \t} else if (os_strcmp(buf, \"STA-FIRST\") == 0) {\n \t\treply_len = hostapd_ctrl_iface_sta_first(hapd, reply,\n \t\t\t\t\t\t\t reply_size);\n@@ -911,6 +985,7 @@ static void hostapd_ctrl_iface_receive(i\n \t} else if (os_strncmp(buf, \"STA-NEXT \", 9) == 0) {\n \t\treply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,\n \t\t\t\t\t\t\treply_size);\n+#endif\n \t} else if (os_strcmp(buf, \"ATTACH\") == 0) {\n \t\tif (hostapd_ctrl_iface_attach(hapd, &from, fromlen))\n \t\t\treply_len = -1;\ndiff -purN hostapd-20130302/hostapd/defconfig hostapd-20130302-linux/hostapd/defconfig\n--- hostapd-20130302/hostapd/defconfig\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/defconfig\t2013-07-04 11:17:51.000000000 -0400\n@@ -267,3 +267,5 @@ CONFIG_IPV6=y\n \n # Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file\n #CONFIG_SQLITE=y\n+\n+CONFIG_DRIVER_CAPWAP_WTP=y\ndiff -purN hostapd-20130302/hostapd/hostapd_ac.conf hostapd-20130302-linux/hostapd/hostapd_ac.conf\n--- hostapd-20130302/hostapd/hostapd_ac.conf\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/hostapd_ac.conf\t2013-07-06 06:07:33.000000000 -0400\n@@ -0,0 +1,3 @@\n+ip_daemon_ac=127.0.0.1\n+sock_path_ac=/tmp/ac_ipc_hostapd\n+port_daemon_ac=5543\ndiff -purN hostapd-20130302/hostapd/hostapd_cli.c hostapd-20130302-linux/hostapd/hostapd_cli.c\n--- hostapd-20130302/hostapd/hostapd_cli.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/hostapd_cli.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -67,7 +67,6 @@ static const char *commands_help =\n #ifdef CONFIG_IEEE80211W\n \"   sa_query <addr>      send SA Query to a station\\n\"\n #endif /* CONFIG_IEEE80211W */\n-#ifdef CONFIG_WPS\n \"   wps_pin <uuid> <pin> [timeout] [addr]  add WPS Enrollee PIN\\n\"\n \"   wps_check_pin <PIN>  verify PIN checksum\\n\"\n \"   wps_pbc              indicate button pushed to initiate PBC\\n\"\n@@ -79,7 +78,6 @@ static const char *commands_help =\n #endif /* CONFIG_WPS_NFC */\n \"   wps_ap_pin <cmd> [params..]  enable/disable AP PIN\\n\"\n \"   wps_config <SSID> <auth> <encr> <key>  configure AP\\n\"\n-#endif /* CONFIG_WPS */\n \"   get_config           show current configuration\\n\"\n \"   help                 show this usage help\\n\"\n \"   interface [ifname]   show interfaces/select interface\\n\"\n@@ -340,7 +338,6 @@ static int hostapd_cli_cmd_sa_query(stru\n #endif /* CONFIG_IEEE80211W */\n \n \n-#ifdef CONFIG_WPS\n static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,\n \t\t\t\t   char *argv[])\n {\n@@ -559,7 +556,6 @@ static int hostapd_cli_cmd_wps_config(st\n \t\t\t ssid_hex, argv[1]);\n \treturn wpa_ctrl_command(ctrl, buf);\n }\n-#endif /* CONFIG_WPS */\n \n \n static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,\n@@ -805,7 +801,6 @@ static struct hostapd_cli_cmd hostapd_cl\n #ifdef CONFIG_IEEE80211W\n \t{ \"sa_query\", hostapd_cli_cmd_sa_query },\n #endif /* CONFIG_IEEE80211W */\n-#ifdef CONFIG_WPS\n \t{ \"wps_pin\", hostapd_cli_cmd_wps_pin },\n \t{ \"wps_check_pin\", hostapd_cli_cmd_wps_check_pin },\n \t{ \"wps_pbc\", hostapd_cli_cmd_wps_pbc },\n@@ -818,7 +813,6 @@ static struct hostapd_cli_cmd hostapd_cl\n #endif /* CONFIG_WPS_NFC */\n \t{ \"wps_ap_pin\", hostapd_cli_cmd_wps_ap_pin },\n \t{ \"wps_config\", hostapd_cli_cmd_wps_config },\n-#endif /* CONFIG_WPS */\n \t{ \"disassoc_imminent\", hostapd_cli_cmd_disassoc_imminent },\n \t{ \"ess_disassoc\", hostapd_cli_cmd_ess_disassoc },\n \t{ \"get_config\", hostapd_cli_cmd_get_config },\ndiff -purN hostapd-20130302/hostapd/hostapd.conf hostapd-20130302-linux/hostapd/hostapd.conf\n--- hostapd-20130302/hostapd/hostapd.conf\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/hostapd.conf\t2013-07-07 01:29:44.000000000 -0400\n@@ -23,6 +23,7 @@ interface=wlan0\n # Use driver=none if building hostapd as a standalone RADIUS server that does\n # not control any wireless/wired driver.\n # driver=hostap\n+driver=capwap\n \n # hostapd event logger configuration\n #\n@@ -83,15 +84,7 @@ ctrl_interface_group=0\n ##### IEEE 802.11 related configuration #######################################\n \n # SSID to be used in IEEE 802.11 management frames\n-ssid=test\n-# Alternative formats for configuring SSID\n-# (double quoted string, hexdump, printf-escaped string)\n-#ssid2=\"test\"\n-#ssid2=74657374\n-#ssid2=P\"hello\\nthere\"\n-\n-# UTF-8 SSID: Whether the SSID is to be interpreted using UTF-8 encoding\n-#utf8_ssid=1\n+ssid=OpenWRT\n \n # Country code (ISO/IEC 3166-1). Used to set regulatory domain.\n # Set as needed to indicate country in which device is operating.\n@@ -106,10 +99,8 @@ ssid=test\n #ieee80211d=1\n \n # Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,\n-# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to\n-# specify band)\n # Default: IEEE 802.11b\n-hw_mode=g\n+hw_mode=b\n \n # Channel number (IEEE 802.11)\n # (default: 0, i.e., not set)\n@@ -171,7 +162,7 @@ fragm_threshold=2346\n # disabled (and enabled when such STAs disassociate) dynamically.\n # 0 = do not allow use of short preamble (default)\n # 1 = allow use of short preamble\n-#preamble=1\n+preamble=1\n \n # Station MAC address -based authentication\n # Please note that this kind of access control requires a driver that uses\n@@ -194,7 +185,7 @@ macaddr_acl=0\n # Bit fields of allowed authentication algorithms:\n # bit 0 = Open System Authentication\n # bit 1 = Shared Key Authentication (requires WEP)\n-auth_algs=3\n+auth_algs=1\n \n # Send empty SSID in beacons and ignore probe request frames that do not\n # specify full SSID, i.e., require stations to know SSID.\n@@ -206,13 +197,6 @@ auth_algs=3\n #     requests for broadcast SSID\n ignore_broadcast_ssid=0\n \n-# Additional vendor specfic elements for Beacon and Probe Response frames\n-# This parameter can be used to add additional vendor specific element(s) into\n-# the end of the Beacon and Probe Response frames. The format for these\n-# element(s) is a hexdump of the raw information elements (id+len+payload for\n-# one or more elements)\n-#vendor_elements=dd0411223301\n-\n # TX queue parameters (EDCF / bursting)\n # tx_queue_<queue name>_<param>\n # queues: data0, data1, data2, data3, after_beacon, beacon\n@@ -356,17 +340,11 @@ wmm_ac_vo_acm=0\n # the STA with a data frame.\n # default: 300 (i.e., 5 minutes)\n #ap_max_inactivity=300\n-#\n-# The inactivity polling can be disabled to disconnect stations based on\n-# inactivity timeout so that idle stations are more likely to be disconnected\n-# even if they are still in range of the AP. This can be done by setting\n-# skip_inactivity_poll to 1 (default 0).\n-#skip_inactivity_poll=0\n \n # Disassociate stations based on excessive transmission failures or other\n # indications of connection loss. This depends on the driver capabilities and\n # may not be available with all drivers.\n-#disassoc_low_ack=1\n+disassoc_low_ack=1\n \n # Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to\n # remain asleep). Default: 65535 (no limit apart from field size)\n@@ -433,161 +411,10 @@ wmm_ac_vo_acm=0\n # Require stations to support HT PHY (reject association if they do not)\n #require_ht=1\n \n-##### IEEE 802.11ac related configuration #####################################\n-\n-# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled\n-# 0 = disabled (default)\n-# 1 = enabled\n-# Note: You will also need to enable WMM for full VHT functionality.\n-#ieee80211ac=1\n-\n-# vht_capab: VHT capabilities (list of flags)\n-#\n-# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]\n-# Indicates maximum MPDU length\n-# 0 = 3895 octets (default)\n-# 1 = 7991 octets\n-# 2 = 11454 octets\n-# 3 = reserved\n-#\n-# supported_chan_width: [VHT160] [VHT160-80PLUS80]\n-# Indicates supported Channel widths\n-# 0 = 160 MHz & 80+80 channel widths are not supported (default)\n-# 1 = 160 MHz channel width is supported\n-# 2 = 160 MHz & 80+80 channel widths are supported\n-# 3 = reserved\n-#\n-# Rx LDPC coding capability: [RXLDPC]\n-# Indicates support for receiving LDPC coded pkts\n-# 0 = Not supported (default)\n-# 1 = Supported\n-#\n-# Short GI for 80 MHz: [SHORT-GI-80]\n-# Indicates short GI support for reception of packets transmitted with TXVECTOR\n-# params format equal to VHT and CBW = 80Mhz\n-# 0 = Not supported (default)\n-# 1 = Supported\n-#\n-# Short GI for 160 MHz: [SHORT-GI-160]\n-# Indicates short GI support for reception of packets transmitted with TXVECTOR\n-# params format equal to VHT and CBW = 160Mhz\n-# 0 = Not supported (default)\n-# 1 = Supported\n-#\n-# Tx STBC: [TX-STBC-2BY1]\n-# Indicates support for the transmission of at least 2x1 STBC\n-# 0 = Not supported (default)\n-# 1 = Supported\n-#\n-# Rx STBC: [RX-STBC-1] [RX-STBC-12] [RX-STBC-123] [RX-STBC-1234]\n-# Indicates support for the reception of PPDUs using STBC\n-# 0 = Not supported (default)\n-# 1 = support of one spatial stream\n-# 2 = support of one and two spatial streams\n-# 3 = support of one, two and three spatial streams\n-# 4 = support of one, two, three and four spatial streams\n-# 5,6,7 = reserved\n-#\n-# SU Beamformer Capable: [SU-BEAMFORMER]\n-# Indicates support for operation as a single user beamformer\n-# 0 = Not supported (default)\n-# 1 = Supported\n-#\n-# SU Beamformee Capable: [SU-BEAMFORMEE]\n-# Indicates support for operation as a single user beamformee\n-# 0 = Not supported (default)\n-# 1 = Supported\n-#\n-# Compressed Steering Number of Beamformer Antennas Supported: [BF-ANTENNA-2]\n-#   Beamformee's capability indicating the maximum number of beamformer\n-#   antennas the beamformee can support when sending compressed beamforming\n-#   feedback\n-# If SU beamformer capable, set to maximum value minus 1\n-# else reserved (default)\n-#\n-# Number of Sounding Dimensions: [SOUNDING-DIMENSION-2]\n-# Beamformer's capability indicating the maximum value of the NUM_STS parameter\n-# in the TXVECTOR of a VHT NDP\n-# If SU beamformer capable, set to maximum value minus 1\n-# else reserved (default)\n-#\n-# MU Beamformer Capable: [MU-BEAMFORMER]\n-# Indicates support for operation as an MU beamformer\n-# 0 = Not supported or sent by Non-AP STA (default)\n-# 1 = Supported\n-#\n-# MU Beamformee Capable: [MU-BEAMFORMEE]\n-# Indicates support for operation as an MU beamformee\n-# 0 = Not supported or sent by AP (default)\n-# 1 = Supported\n-#\n-# VHT TXOP PS: [VHT-TXOP-PS]\n-# Indicates whether or not the AP supports VHT TXOP Power Save Mode\n-#  or whether or not the STA is in VHT TXOP Power Save mode\n-# 0 = VHT AP doesnt support VHT TXOP PS mode (OR) VHT Sta not in VHT TXOP PS\n-#  mode\n-# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT Sta is in VHT TXOP power save\n-#  mode\n-#\n-# +HTC-VHT Capable: [HTC-VHT]\n-# Indicates whether or not the STA supports receiving a VHT variant HT Control\n-# field.\n-# 0 = Not supported (default)\n-# 1 = supported\n-#\n-# Maximum A-MPDU Length Exponent: [MAX-A-MPDU-LEN-EXP0]..[MAX-A-MPDU-LEN-EXP7]\n-# Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv\n-# This field is an integer in the range of 0 to 7.\n-# The length defined by this field is equal to\n-# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets\n-#\n-# VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3]\n-# Indicates whether or not the STA supports link adaptation using VHT variant\n-# HT Control field\n-# If +HTC-VHTcapable is 1\n-#  0 = (no feedback) if the STA does not provide VHT MFB (default)\n-#  1 = reserved\n-#  2 = (Unsolicited) if the STA provides only unsolicited VHT MFB\n-#  3 = (Both) if the STA can provide VHT MFB in response to VHT MRQ and if the\n-#      STA provides unsolicited VHT MFB\n-# Reserved if +HTC-VHTcapable is 0\n-#\n-# Rx Antenna Pattern Consistency: [RX-ANTENNA-PATTERN]\n-# Indicates the possibility of Rx antenna pattern change\n-# 0 = Rx antenna pattern might change during the lifetime of an association\n-# 1 = Rx antenna pattern does not change during the lifetime of an association\n-#\n-# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN]\n-# Indicates the possibility of Tx antenna pattern change\n-# 0 = Tx antenna pattern might change during the lifetime of an association\n-# 1 = Tx antenna pattern does not change during the lifetime of an association\n-#vht_capab=[SHORT-GI-80][HTC-VHT]\n-#\n-# Require stations to support VHT PHY (reject association if they do not)\n-#require_vht=1\n-\n-# 0 = 20 or 40 MHz operating Channel width\n-# 1 = 80 MHz channel width\n-# 2 = 160 MHz channel width\n-# 3 = 80+80 MHz channel width\n-#vht_oper_chwidth=1\n-#\n-# center freq = 5 GHz + (5 * index)\n-# So index 42 gives center freq 5.210 GHz\n-# which is channel 42 in 5G band\n-#\n-#vht_oper_centr_freq_seg0_idx=42\n-#\n-# center freq = 5 GHz + (5 * index)\n-# So index 159 gives center freq 5.795 GHz\n-# which is channel 159 in 5G band\n-#\n-#vht_oper_centr_freq_seg1_idx=159\n-\n ##### IEEE 802.1X-2004 related configuration ##################################\n \n # Require IEEE 802.1X authorization\n-#ieee8021x=1\n+ieee8021x=1\n \n # IEEE 802.1X/EAPOL version\n # hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL\n@@ -615,7 +442,7 @@ wmm_ac_vo_acm=0\n \n # EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if\n # only broadcast keys are used)\n-eapol_key_index_workaround=0\n+eapol_key_index_workaround=1\n \n # EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable\n # reauthentication).\n@@ -640,8 +467,6 @@ eapol_key_index_workaround=0\n eap_server=0\n \n # Path for EAP server user database\n-# If SQLite support is included, this can be set to \"sqlite:/path/to/sqlite.db\"\n-# to use SQLite database instead of a text file.\n #eap_user_file=/etc/hostapd.eap_user\n \n # CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS\n@@ -686,18 +511,12 @@ eap_server=0\n # Fragment size for EAP methods\n #fragment_size=1400\n \n-# Finite cyclic group for EAP-pwd. Number maps to group of domain parameters\n-# using the IANA repository for IKE (RFC 2409).\n-#pwd_group=19\n-\n # Configuration data for EAP-SIM database/authentication gateway interface.\n # This is a text string in implementation specific format. The example\n # implementation in eap_sim_db.c uses this as the UNIX domain socket name for\n # the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses \"unix:\"\n-# prefix. If hostapd is built with SQLite support (CONFIG_SQLITE=y in .config),\n-# database file can be described with an optional db=<path> parameter.\n+# prefix.\n #eap_sim_db=unix:/tmp/hlr_auc_gw.sock\n-#eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db\n \n # Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,\n # random value. It is configured as a 16-octet value in hex format. It can be\n@@ -763,12 +582,12 @@ own_ip_addr=127.0.0.1\n # fully qualified domain name can be used here.\n # When using IEEE 802.11r, nas_identifier must be set and must be between 1 and\n # 48 octets long.\n-#nas_identifier=ap.example.com\n+nas_identifier=OpenWrt\n \n # RADIUS authentication server\n-#auth_server_addr=127.0.0.1\n-#auth_server_port=1812\n-#auth_server_shared_secret=secret\n+auth_server_addr=31.1.1.1\n+auth_server_port=1812\n+auth_server_shared_secret=SharedSecret\n \n # RADIUS accounting server\n #acct_server_addr=127.0.0.1\n@@ -804,12 +623,6 @@ own_ip_addr=127.0.0.1\n # 60 (1 minute).\n #radius_acct_interim_interval=600\n \n-# Request Chargeable-User-Identity (RFC 4372)\n-# This parameter can be used to configure hostapd to request CUI from the\n-# RADIUS server by including Chargeable-User-Identity attribute into\n-# Access-Request packets.\n-#radius_request_cui=1\n-\n # Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN\n # is used for the stations. This information is parsed from following RADIUS\n # attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),\n@@ -837,61 +650,6 @@ own_ip_addr=127.0.0.1\n # to the bridge.\n #vlan_tagged_interface=eth0\n \n-# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs\n-# to know how to name it.\n-# 0 = vlan<XXX>, e.g., vlan1\n-# 1 = <vlan_tagged_interface>.<XXX>, e.g. eth0.1\n-#vlan_naming=0\n-\n-# Arbitrary RADIUS attributes can be added into Access-Request and\n-# Accounting-Request packets by specifying the contents of the attributes with\n-# the following configuration parameters. There can be multiple of these to\n-# add multiple attributes. These parameters can also be used to override some\n-# of the attributes added automatically by hostapd.\n-# Format: <attr_id>[:<syntax:value>]\n-# attr_id: RADIUS attribute type (e.g., 26 = Vendor-Specific)\n-# syntax: s = string (UTF-8), d = integer, x = octet string\n-# value: attribute value in format indicated by the syntax\n-# If syntax and value parts are omitted, a null value (single 0x00 octet) is\n-# used.\n-#\n-# Additional Access-Request attributes\n-# radius_auth_req_attr=<attr_id>[:<syntax:value>]\n-# Examples:\n-# Operator-Name = \"Operator\"\n-#radius_auth_req_attr=126:s:Operator\n-# Service-Type = Framed (2)\n-#radius_auth_req_attr=6:d:2\n-# Connect-Info = \"testing\" (this overrides the automatically generated value)\n-#radius_auth_req_attr=77:s:testing\n-# Same Connect-Info value set as a hexdump\n-#radius_auth_req_attr=77:x:74657374696e67\n-\n-#\n-# Additional Accounting-Request attributes\n-# radius_acct_req_attr=<attr_id>[:<syntax:value>]\n-# Examples:\n-# Operator-Name = \"Operator\"\n-#radius_acct_req_attr=126:s:Operator\n-\n-# Dynamic Authorization Extensions (RFC 5176)\n-# This mechanism can be used to allow dynamic changes to user session based on\n-# commands from a RADIUS server (or some other disconnect client that has the\n-# needed session information). For example, Disconnect message can be used to\n-# request an associated station to be disconnected.\n-#\n-# This is disabled by default. Set radius_das_port to non-zero UDP port\n-# number to enable.\n-#radius_das_port=3799\n-#\n-# DAS client (the host that can send Disconnect/CoA requests) and shared secret\n-#radius_das_client=192.168.1.123 shared secret here\n-#\n-# DAS Event-Timestamp time window in seconds\n-#radius_das_time_window=300\n-#\n-# DAS require Event-Timestamp\n-#radius_das_require_event_timestamp=1\n \n ##### RADIUS authentication server configuration ##############################\n \n@@ -915,7 +673,6 @@ own_ip_addr=127.0.0.1\n # Enable WPA. Setting this variable configures the AP to require WPA (either\n # WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either\n # wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.\n-# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice.\n # For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),\n # RADIUS authentication server must be configured, and WPA-EAP must be included\n # in wpa_key_mgmt.\n@@ -923,7 +680,7 @@ own_ip_addr=127.0.0.1\n # and/or WPA2 (full IEEE 802.11i/RSN):\n # bit0 = WPA\n # bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)\n-#wpa=1\n+wpa=2\n \n # WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit\n # secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase\n@@ -940,20 +697,11 @@ own_ip_addr=127.0.0.1\n # configuration reloads.\n #wpa_psk_file=/etc/hostapd.wpa_psk\n \n-# Optionally, WPA passphrase can be received from RADIUS authentication server\n-# This requires macaddr_acl to be set to 2 (RADIUS)\n-# 0 = disabled (default)\n-# 1 = optional; use default passphrase/psk if RADIUS server does not include\n-#\tTunnel-Password\n-# 2 = required; reject authentication if RADIUS server does not include\n-#\tTunnel-Password\n-#wpa_psk_radius=0\n-\n # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The\n # entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be\n # added to enable SHA256-based stronger algorithms.\n # (dot11RSNAConfigAuthenticationSuitesTable)\n-#wpa_key_mgmt=WPA-PSK WPA-EAP\n+wpa_key_mgmt=WPA-EAP\n \n # Set of accepted cipher suites (encryption algorithms) for pairwise keys\n # (unicast packets). This is a space separated list of algorithms:\n@@ -965,7 +713,7 @@ own_ip_addr=127.0.0.1\n # TKIP will be used as the group cipher.\n # (dot11RSNAConfigPairwiseCiphersTable)\n # Pairwise cipher for WPA (v1) (default: TKIP)\n-#wpa_pairwise=TKIP CCMP\n+wpa_pairwise=CCMP\n # Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)\n #rsn_pairwise=CCMP\n \n@@ -1028,28 +776,15 @@ own_ip_addr=127.0.0.1\n # it is enabled (rsn_preauth=1).\n # 0 = PMKSA caching enabled (default)\n # 1 = PMKSA caching disabled\n-#disable_pmksa_caching=0\n+disable_pmksa_caching=0\n \n # okc: Opportunistic Key Caching (aka Proactive Key Caching)\n # Allow PMK cache to be shared opportunistically among configured interfaces\n # and BSSes (i.e., all configurations within a single hostapd process).\n # 0 = disabled (default)\n # 1 = enabled\n-#okc=1\n+okc=0\n \n-# SAE threshold for anti-clogging mechanism (dot11RSNASAEAntiCloggingThreshold)\n-# This parameter defines how many open SAE instances can be in progress at the\n-# same time before the anti-clogging mechanism is taken into use.\n-#sae_anti_clogging_threshold=5\n-\n-# Enabled SAE finite cyclic groups\n-# SAE implementation are required to support group 19 (ECC group defined over a\n-# 256-bit prime order field). All groups that are supported by the\n-# implementation are enabled by default. This configuration parameter can be\n-# used to specify a limited set of allowed groups. The group values are listed\n-# in the IANA registry:\n-# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-9\n-#sae_groups=19 20 21 25 26\n \n ##### IEEE 802.11r configuration ##############################################\n \n@@ -1273,24 +1008,6 @@ own_ip_addr=127.0.0.1\n # 12-digit, all-numeric code that identifies the consumer package.\n #upc=123456789012\n \n-# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band)\n-# This value should be set according to RF band(s) supported by the AP if\n-# hw_mode is not set. For dual band dual concurrent devices, this needs to be\n-# set to ag to allow both RF bands to be advertized.\n-#wps_rf_bands=ag\n-\n-# NFC password token for WPS\n-# These parameters can be used to configure a fixed NFC password token for the\n-# AP. This can be generated, e.g., with nfc_pw_token from wpa_supplicant. When\n-# these parameters are used, the AP is assumed to be deployed with a NFC tag\n-# that includes the matching NFC password token (e.g., written based on the\n-# NDEF record from nfc_pw_token).\n-#\n-#wps_nfc_dev_pw_id: Device Password ID (16..65535)\n-#wps_nfc_dh_pubkey: Hexdump of DH Public Key\n-#wps_nfc_dh_privkey: Hexdump of DH Private Key\n-#wps_nfc_dev_pw: Hexdump of Device Password\n-\n ##### Wi-Fi Direct (P2P) ######################################################\n \n # Enable P2P Device management\n@@ -1318,16 +1035,6 @@ own_ip_addr=127.0.0.1\n # stdoffset[dst[offset][,start[/time],end[/time]]]\n #time_zone=EST5\n \n-# WNM-Sleep Mode (extended sleep mode for stations)\n-# 0 = disabled (default)\n-# 1 = enabled (allow stations to use WNM-Sleep Mode)\n-#wnm_sleep_mode=1\n-\n-# BSS Transition Management\n-# 0 = disabled (default)\n-# 1 = enabled\n-#bss_transition=1\n-\n ##### IEEE 802.11u-2011 #######################################################\n \n # Enable Interworking service\n@@ -1381,138 +1088,11 @@ own_ip_addr=127.0.0.1\n # Arbitrary number of Roaming Consortium OIs can be configured with each line\n # adding a new OI to the list. The first three entries are available through\n # Beacon and Probe Response frames. Any additional entry will be available only\n-# through ANQP queries. Each OI is between 3 and 15 octets and is configured as\n+# through ANQP queries. Each OI is between 3 and 15 octets and is configured a\n # a hexstring.\n #roaming_consortium=021122\n #roaming_consortium=2233445566\n \n-# Venue Name information\n-# This parameter can be used to configure one or more Venue Name Duples for\n-# Venue Name ANQP information. Each entry has a two or three character language\n-# code (ISO-639) separated by colon from the venue name string.\n-# Note that venue_group and venue_type have to be set for Venue Name\n-# information to be complete.\n-#venue_name=eng:Example venue\n-#venue_name=fin:Esimerkkipaikka\n-\n-# Network Authentication Type\n-# This parameter indicates what type of network authentication is used in the\n-# network.\n-# format: <network auth type indicator (1-octet hex str)> [redirect URL]\n-# Network Authentication Type Indicator values:\n-# 00 = Acceptance of terms and conditions\n-# 01 = On-line enrollment supported\n-# 02 = http/https redirection\n-# 03 = DNS redirection\n-#network_auth_type=00\n-#network_auth_type=02http://www.example.com/redirect/me/here/\n-\n-# IP Address Type Availability\n-# format: <1-octet encoded value as hex str>\n-# (ipv4_type & 0x3f) << 2 | (ipv6_type & 0x3)\n-# ipv4_type:\n-# 0 = Address type not available\n-# 1 = Public IPv4 address available\n-# 2 = Port-restricted IPv4 address available\n-# 3 = Single NATed private IPv4 address available\n-# 4 = Double NATed private IPv4 address available\n-# 5 = Port-restricted IPv4 address and single NATed IPv4 address available\n-# 6 = Port-restricted IPv4 address and double NATed IPv4 address available\n-# 7 = Availability of the address type is not known\n-# ipv6_type:\n-# 0 = Address type not available\n-# 1 = Address type available\n-# 2 = Availability of the address type not known\n-#ipaddr_type_availability=14\n-\n-# Domain Name\n-# format: <variable-octet str>[,<variable-octet str>]\n-#domain_name=example.com,another.example.com,yet-another.example.com\n-\n-# 3GPP Cellular Network information\n-# format: <MCC1,MNC1>[;<MCC2,MNC2>][;...]\n-#anqp_3gpp_cell_net=244,91;310,026;234,56\n-\n-# NAI Realm information\n-# One or more realm can be advertised. Each nai_realm line adds a new realm to\n-# the set. These parameters provide information for stations using Interworking\n-# network selection to allow automatic connection to a network based on\n-# credentials.\n-# format: <encoding>,<NAI Realm(s)>[,<EAP Method 1>][,<EAP Method 2>][,...]\n-# encoding:\n-#\t0 = Realm formatted in accordance with IETF RFC 4282\n-#\t1 = UTF-8 formatted character string that is not formatted in\n-#\t    accordance with IETF RFC 4282\n-# NAI Realm(s): Semi-colon delimited NAI Realm(s)\n-# EAP Method: <EAP Method>[:<[AuthParam1:Val1]>][<[AuthParam2:Val2]>][...]\n-# AuthParam (Table 8-188 in IEEE Std 802.11-2012):\n-# ID 2 = Non-EAP Inner Authentication Type\n-#\t1 = PAP, 2 = CHAP, 3 = MSCHAP, 4 = MSCHAPV2\n-# ID 3 = Inner authentication EAP Method Type\n-# ID 5 = Credential Type\n-#\t1 = SIM, 2 = USIM, 3 = NFC Secure Element, 4 = Hardware Token,\n-#\t5 = Softoken, 6 = Certificate, 7 = username/password, 9 = Anonymous,\n-#\t10 = Vendor Specific\n-#nai_realm=0,example.com;example.net\n-# EAP methods EAP-TLS with certificate and EAP-TTLS/MSCHAPv2 with\n-# username/password\n-#nai_realm=0,example.org,13[5:6],21[2:4][5:7]\n-\n-##### Hotspot 2.0 #############################################################\n-\n-# Enable Hotspot 2.0 support\n-#hs20=1\n-\n-# Disable Downstream Group-Addressed Forwarding (DGAF)\n-# This can be used to configure a network where no group-addressed frames are\n-# allowed. The AP will not forward any group-address frames to the stations and\n-# random GTKs are issued for each station to prevent associated stations from\n-# forging such frames to other stations in the BSS.\n-#disable_dgaf=1\n-\n-# Operator Friendly Name\n-# This parameter can be used to configure one or more Operator Friendly Name\n-# Duples. Each entry has a two or three character language code (ISO-639)\n-# separated by colon from the operator friendly name string.\n-#hs20_oper_friendly_name=eng:Example operator\n-#hs20_oper_friendly_name=fin:Esimerkkioperaattori\n-\n-# Connection Capability\n-# This can be used to advertise what type of IP traffic can be sent through the\n-# hotspot (e.g., due to firewall allowing/blocking protocols/ports).\n-# format: <IP Protocol>:<Port Number>:<Status>\n-# IP Protocol: 1 = ICMP, 6 = TCP, 17 = UDP\n-# Port Number: 0..65535\n-# Status: 0 = Closed, 1 = Open, 2 = Unknown\n-# Each hs20_conn_capab line is added to the list of advertised tuples.\n-#hs20_conn_capab=1:0:2\n-#hs20_conn_capab=6:22:1\n-#hs20_conn_capab=17:5060:0\n-\n-# WAN Metrics\n-# format: <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD>\n-# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capabity\n-#    (encoded as two hex digits)\n-#    Link Status: 1 = Link up, 2 = Link down, 3 = Link in test state\n-# Downlink Speed: Estimate of WAN backhaul link current downlink speed in kbps;\n-#\t1..4294967295; 0 = unknown\n-# Uplink Speed: Estimate of WAN backhaul link current uplink speed in kbps\n-#\t1..4294967295; 0 = unknown\n-# Downlink Load: Current load of downlink WAN connection (scaled to 255 = 100%)\n-# Uplink Load: Current load of uplink WAN connection (scaled to 255 = 100%)\n-# Load Measurement Duration: Duration for measuring downlink/uplink load in\n-# tenths of a second (1..65535); 0 if load cannot be determined\n-#hs20_wan_metrics=01:8000:1000:80:240:3000\n-\n-# Operating Class Indication\n-# List of operating classes the BSSes in this ESS use. The Global operating\n-# classes in Table E-4 of IEEE Std 802.11-2012 Annex E define the values that\n-# can be used in this.\n-# format: hexdump of operating class octets\n-# for example, operating classes 81 (2.4 GHz channels 1-13) and 115 (5 GHz\n-# channels 36-48):\n-#hs20_operating_class=5173\n-\n ##### Multiple BSSID support ##################################################\n #\n # Above configuration is using the default interface (wlan#, or multi-SSID VLAN\ndiff -purN hostapd-20130302/hostapd/main.c hostapd-20130302-linux/hostapd/main.c\n--- hostapd-20130302/hostapd/main.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/main.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -13,6 +13,7 @@\n \n #include \"utils/common.h\"\n #include \"utils/eloop.h\"\n+#include \"utils/build_features.h\"\n #include \"crypto/random.h\"\n #include \"crypto/tls.h\"\n #include \"common/version.h\"\n@@ -31,6 +32,8 @@\n extern int wpa_debug_level;\n extern int wpa_debug_show_keys;\n extern int wpa_debug_timestamp;\n+static int daemonize = 0;\n+static char *pid_file = NULL;\n \n extern struct wpa_driver_ops *wpa_drivers[];\n \n@@ -145,6 +148,14 @@ static void hostapd_logger_cb(void *ctx,\n }\n #endif /* CONFIG_NO_HOSTAPD_LOGGER */\n \n+static void hostapd_setup_complete_cb(void *ctx)\n+{\n+\tif (daemonize && os_daemonize(pid_file)) {\n+\t\tperror(\"daemon\");\n+\t\treturn;\n+\t}\n+\tdaemonize = 0;\n+}\n \n /**\n  * hostapd_init - Allocate and initialize per-interface data\n@@ -188,6 +199,7 @@ static struct hostapd_iface * hostapd_in\n \t\tif (hapd == NULL)\n \t\t\tgoto fail;\n \t\thapd->msg_ctx = hapd;\n+\t\thapd->setup_complete_cb = hostapd_setup_complete_cb;\n \t}\n \n \treturn hapd_iface;\n@@ -424,8 +436,6 @@ static void hostapd_global_deinit(const\n #endif /* CONFIG_NATIVE_WINDOWS */\n \n \teap_server_unregister_methods();\n-\n-\tos_daemonize_terminate(pid_file);\n }\n \n \n@@ -451,11 +461,6 @@ static int hostapd_global_run(struct hap\n \t}\n #endif /* EAP_SERVER_TNC */\n \n-\tif (daemonize && os_daemonize(pid_file)) {\n-\t\tperror(\"daemon\");\n-\t\treturn -1;\n-\t}\n-\n \teloop_run();\n \n \treturn 0;\n@@ -530,14 +535,16 @@ static int hostapd_get_global_ctrl_iface\n \treturn 0;\n }\n \n+void hostapd_wpa_event(void *ctx, enum wpa_event_type event,\n+                       union wpa_event_data *data);\n+\n \n int main(int argc, char *argv[])\n {\n \tstruct hapd_interfaces interfaces;\n \tint ret = 1;\n \tsize_t i;\n-\tint c, debug = 0, daemonize = 0;\n-\tchar *pid_file = NULL;\n+\tint c, debug = 0;\n \tconst char *log_file = NULL;\n \tconst char *entropy_file = NULL;\n \n@@ -555,8 +562,9 @@ int main(int argc, char *argv[])\n \tinterfaces.global_iface_name = NULL;\n \tinterfaces.global_ctrl_sock = -1;\n \n+\twpa_supplicant_event = hostapd_wpa_event;\n \tfor (;;) {\n-\t\tc = getopt(argc, argv, \"Bde:f:hKP:tvg:\");\n+\t\tc = getopt(argc, argv, \"Bde:f:hKP:tg:v::\");\n \t\tif (c < 0)\n \t\t\tbreak;\n \t\tswitch (c) {\n@@ -588,6 +596,8 @@ int main(int argc, char *argv[])\n \t\t\twpa_debug_timestamp++;\n \t\t\tbreak;\n \t\tcase 'v':\n+\t\t\tif (optarg)\n+\t\t\t\texit(!has_feature(optarg));\n \t\t\tshow_version();\n \t\t\texit(1);\n \t\t\tbreak;\ndiff -purN hostapd-20130302/hostapd/Makefile hostapd-20130302-linux/hostapd/Makefile\n--- hostapd-20130302/hostapd/Makefile\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/hostapd/Makefile\t2013-07-06 06:13:59.000000000 -0400\n@@ -6,7 +6,7 @@ ifndef CFLAGS\n CFLAGS = -MMD -O2 -Wall -g\n endif\n \n-CFLAGS += -I../src\n+CFLAGS += -I../src -D__USE_GNU\n CFLAGS += -I../src/utils\n \n # Uncomment following line and set the path to your kernel tree include\n@@ -14,6 +14,7 @@ CFLAGS += -I../src/utils\n # CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include\n \n -include .config\n+-include $(if $(MULTICALL), ../wpa_supplicant/.config)\n \n ifndef CONFIG_OS\n ifdef CONFIG_NATIVE_WINDOWS\n@@ -135,6 +136,9 @@ endif\n ifdef CONFIG_NO_CTRL_IFACE\n CFLAGS += -DCONFIG_NO_CTRL_IFACE\n else\n+ifdef CONFIG_CTRL_IFACE_MIB\n+CFLAGS += -DCONFIG_CTRL_IFACE_MIB\n+endif\n OBJS += ctrl_iface.o\n OBJS += ../src/ap/ctrl_iface_ap.o\n endif\n@@ -192,10 +196,14 @@ ifdef CONFIG_IEEE80211AC\n CFLAGS += -DCONFIG_IEEE80211AC\n endif\n \n+ifndef MULTICALL\n+CFLAGS += -DNO_SUPPLICANT\n+endif\n+\n include ../src/drivers/drivers.mak\n-OBJS += $(DRV_AP_OBJS)\n-CFLAGS += $(DRV_AP_CFLAGS)\n-LDFLAGS += $(DRV_AP_LDFLAGS)\n+OBJS += $(sort $(DRV_AP_OBJS) $(if $(MULTICALL),$(DRV_WPA_OBJS)))\n+CFLAGS += $(DRV_AP_CFLAGS) $(if $(MULTICALL),$(DRV_WPA_CFLAGS))\n+LDFLAGS += $(DRV_AP_LDFLAGS) $(if $(MULTICALL),$(DRV_WPA_LDFLAGS))\n LIBS += $(DRV_AP_LIBS)\n \n ifdef CONFIG_L2_PACKET\n@@ -860,6 +868,12 @@ install: all\n \n BCHECK=../src/drivers/build.hostapd\n \n+hostapd_multi.a: $(BCHECK) $(OBJS)\n+\t$(Q)$(CC) -c -o hostapd_multi.o -Dmain=hostapd_main $(CFLAGS) main.c\n+\t@$(E) \"  CC \" $<\n+\t@rm -f $@\n+\t@$(AR) cr $@ hostapd_multi.o $(OBJS)\n+\n hostapd: $(BCHECK) $(OBJS)\n \t$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)\n \t@$(E) \"  LD \" $@\n@@ -898,6 +912,12 @@ HOBJS += ../src/crypto/aes-internal.o\n HOBJS += ../src/crypto/aes-internal-enc.o\n endif\n \n+dump_cflags:\n+\t@echo -n $(CFLAGS) \" \"\n+\n+dump_ldflags:\n+\t@echo -n $(LDFLAGS) $(LIBS) $(EXTRALIBS) \" \"\n+\n nt_password_hash: $(NOBJS)\n \t$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)\n \t@$(E) \"  LD \" $@\ndiff -purN hostapd-20130302/src/ap/ap_config.h hostapd-20130302-linux/src/ap/ap_config.h\n--- hostapd-20130302/src/ap/ap_config.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/ap_config.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -510,9 +510,11 @@ struct hostapd_config {\n \n \tint ht_op_mode_fixed;\n \tu16 ht_capab;\n+\tint noscan;\n \tint ieee80211n;\n \tint secondary_channel;\n \tint require_ht;\n+\tint dynamic_ht40;\n \tu32 vht_capab;\n \tint ieee80211ac;\n \tint require_vht;\ndiff -purN hostapd-20130302/src/ap/beacon.c hostapd-20130302-linux/src/ap/beacon.c\n--- hostapd-20130302/src/ap/beacon.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/beacon.c\t2013-07-06 06:11:10.000000000 -0400\n@@ -455,6 +455,10 @@ void handle_probe_req(struct hostapd_dat\n \t\treturn;\n \t}\n \n+\tif (!sta && hapd->num_sta >= hapd->conf->max_num_sta)\n+\t\twpa_printf(MSG_MSGDUMP, \"Probe Request from \" MACSTR \" ignored,\"\n+\t\t\t   \" too many connected stations.\", MAC2STR(mgmt->sa));\n+\n #ifdef CONFIG_INTERWORKING\n \tif (elems.interworking && elems.interworking_len >= 1) {\n \t\tu8 ant = elems.interworking[0] & 0x0f;\ndiff -purN hostapd-20130302/src/ap/ctrl_iface_ap.c hostapd-20130302-linux/src/ap/ctrl_iface_ap.c\n--- hostapd-20130302/src/ap/ctrl_iface_ap.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/ctrl_iface_ap.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -20,6 +20,7 @@\n #include \"ctrl_iface_ap.h\"\n #include \"ap_drv_ops.h\"\n \n+#ifdef CONFIG_CTRL_IFACE_MIB\n \n static int hostapd_get_sta_conn_time(struct sta_info *sta,\n \t\t\t\t     char *buf, size_t buflen)\n@@ -129,6 +130,7 @@ int hostapd_ctrl_iface_sta_next(struct h\n \treturn hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);\n }\n \n+#endif\n \n #ifdef CONFIG_P2P_MANAGER\n static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,\n@@ -303,3 +305,4 @@ int hostapd_ctrl_iface_disassociate(stru\n \n \treturn 0;\n }\n+\ndiff -purN hostapd-20130302/src/ap/drv_callbacks.c hostapd-20130302-linux/src/ap/drv_callbacks.c\n--- hostapd-20130302/src/ap/drv_callbacks.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/drv_callbacks.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -714,8 +714,8 @@ static void hostapd_event_eapol_rx(struc\n }\n \n \n-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,\n-\t\t\t  union wpa_event_data *data)\n+void hostapd_wpa_event(void *ctx, enum wpa_event_type event,\n+\t\t       union wpa_event_data *data)\n {\n \tstruct hostapd_data *hapd = ctx;\n #ifndef CONFIG_NO_STDOUT_DEBUG\ndiff -purN hostapd-20130302/src/ap/hostapd.c hostapd-20130302-linux/src/ap/hostapd.c\n--- hostapd-20130302/src/ap/hostapd.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/hostapd.c\t2013-07-06 06:11:10.000000000 -0400\n@@ -22,6 +22,7 @@\n #include \"beacon.h\"\n #include \"iapp.h\"\n #include \"ieee802_1x.h\"\n+#include \"ieee802_11.h\"\n #include \"ieee802_11_auth.h\"\n #include \"vlan_init.h\"\n #include \"wpa_auth.h\"\n@@ -140,6 +141,24 @@ int hostapd_reload_config(struct hostapd\n \toldconf = hapd->iconf;\n \tiface->conf = newconf;\n \n+\thostapd_select_hw_mode(iface);\n+\tiface->freq = hostapd_hw_get_freq(hapd, newconf->channel);\n+\n+\tif (hostapd_set_freq(hapd, newconf->hw_mode, iface->freq,\n+\t\t\t     newconf->channel,\n+\t\t\t     newconf->ieee80211n,\n+\t\t\t     newconf->ieee80211ac,\n+\t\t\t     newconf->secondary_channel,\n+\t\t\t     newconf->vht_oper_chwidth,\n+\t\t\t     newconf->vht_oper_centr_freq_seg0_idx,\n+\t\t\t     newconf->vht_oper_centr_freq_seg1_idx)) {\n+\t\twpa_printf(MSG_ERROR, \"Could not set channel for \"\n+\t\t\t   \"kernel driver\");\n+\t}\n+\n+\tif (iface->current_mode)\n+\t\thostapd_prepare_rates(iface, iface->current_mode);\n+\n \tfor (j = 0; j < iface->num_bss; j++) {\n \t\thapd = iface->bss[j];\n \t\thapd->iconf = newconf;\n@@ -314,6 +333,7 @@ static void hostapd_cleanup_iface_pre(st\n \n static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)\n {\n+\thostapd_deinit_ht(iface);\n \thostapd_free_hw_features(iface->hw_features, iface->num_hw_features);\n \tiface->hw_features = NULL;\n \tos_free(iface->current_rates);\n@@ -877,11 +897,8 @@ int hostapd_setup_interface_complete(str\n \tsize_t j;\n \tu8 *prev_addr;\n \n-\tif (err) {\n-\t\twpa_printf(MSG_ERROR, \"Interface initialization failed\");\n-\t\teloop_terminate();\n-\t\treturn -1;\n-\t}\n+\tif (err)\n+\t\tgoto error;\n \n \twpa_printf(MSG_DEBUG, \"Completing interface initialization\");\n \tif (hapd->iconf->channel) {\n@@ -901,7 +918,7 @@ int hostapd_setup_interface_complete(str\n \t\t\t\t     hapd->iconf->vht_oper_centr_freq_seg1_idx)) {\n \t\t\twpa_printf(MSG_ERROR, \"Could not set channel for \"\n \t\t\t\t   \"kernel driver\");\n-\t\t\treturn -1;\n+\t\t\tgoto error;\n \t\t}\n \t}\n \n@@ -912,7 +929,7 @@ int hostapd_setup_interface_complete(str\n \t\t\thostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,\n \t\t\t\t       HOSTAPD_LEVEL_WARNING,\n \t\t\t\t       \"Failed to prepare rates table.\");\n-\t\t\treturn -1;\n+\t\t\tgoto error;\n \t\t}\n \t}\n \n@@ -920,14 +937,14 @@ int hostapd_setup_interface_complete(str\n \t    hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {\n \t\twpa_printf(MSG_ERROR, \"Could not set RTS threshold for \"\n \t\t\t   \"kernel driver\");\n-\t\treturn -1;\n+\t\tgoto error;\n \t}\n \n \tif (hapd->iconf->fragm_threshold > -1 &&\n \t    hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {\n \t\twpa_printf(MSG_ERROR, \"Could not set fragmentation threshold \"\n \t\t\t   \"for kernel driver\");\n-\t\treturn -1;\n+\t\tgoto error;\n \t}\n \n \tprev_addr = hapd->own_addr;\n@@ -937,7 +954,7 @@ int hostapd_setup_interface_complete(str\n \t\tif (j)\n \t\t\tos_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);\n \t\tif (hostapd_setup_bss(hapd, j == 0))\n-\t\t\treturn -1;\n+\t\t\tgoto error;\n \t\tif (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)\n \t\t\tprev_addr = hapd->own_addr;\n \t}\n@@ -949,7 +966,7 @@ int hostapd_setup_interface_complete(str\n \tif (hostapd_driver_commit(hapd) < 0) {\n \t\twpa_printf(MSG_ERROR, \"%s: Failed to commit driver \"\n \t\t\t   \"configuration\", __func__);\n-\t\treturn -1;\n+\t\tgoto error;\n \t}\n \n \t/*\n@@ -970,6 +987,11 @@ int hostapd_setup_interface_complete(str\n \t\t   iface->bss[0]->conf->iface);\n \n \treturn 0;\n+\n+error:\n+\twpa_printf(MSG_ERROR, \"Interface initialization failed\");\n+\teloop_terminate();\n+\treturn -1;\n }\n \n \ndiff -purN hostapd-20130302/src/ap/hostapd.h hostapd-20130302-linux/src/ap/hostapd.h\n--- hostapd-20130302/src/ap/hostapd.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/hostapd.h\t2013-07-06 06:11:10.000000000 -0400\n@@ -265,6 +265,9 @@ struct hostapd_iface {\n \t/* Overlapping BSS information */\n \tint olbc_ht;\n \n+\tint force_20mhz;\n+\tstruct os_time last_20mhz_trigger;\n+\n \tu16 ht_op_mode;\n \tvoid (*scan_cb)(struct hostapd_iface *iface);\n };\ndiff -purN hostapd-20130302/src/ap/hw_features.c hostapd-20130302-linux/src/ap/hw_features.c\n--- hostapd-20130302/src/ap/hw_features.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/hw_features.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -494,7 +494,7 @@ static int ieee80211n_check_40mhz(struct\n {\n \tstruct wpa_driver_scan_params params;\n \n-\tif (!iface->conf->secondary_channel)\n+\tif (!iface->conf->secondary_channel || iface->conf->noscan)\n \t\treturn 0; /* HT40 not used */\n \n \twpa_printf(MSG_DEBUG, \"Scan for neighboring BSSes prior to enabling \"\ndiff -purN hostapd-20130302/src/ap/ieee802_11.c hostapd-20130302-linux/src/ap/ieee802_11.c\n--- hostapd-20130302/src/ap/ieee802_11.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/ieee802_11.c\t2013-07-06 06:11:10.000000000 -0400\n@@ -1484,6 +1484,9 @@ static void handle_beacon(struct hostapd\n \t\t\t\t\t     sizeof(mgmt->u.beacon)), &elems,\n \t\t\t\t      0);\n \n+\tif (!elems.ht_capabilities)\n+\t\thostapd_trigger_20mhz(hapd->iface);\n+\n \tap_list_process_beacon(hapd->iface, mgmt, &elems, fi);\n }\n \ndiff -purN hostapd-20130302/src/ap/ieee802_11.h hostapd-20130302-linux/src/ap/ieee802_11.h\n--- hostapd-20130302/src/ap/ieee802_11.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/ieee802_11.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -81,4 +81,17 @@ int hostapd_update_time_adv(struct hosta\n void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);\n u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);\n \n+#ifdef CONFIG_IEEE80211N\n+void hostapd_trigger_20mhz(struct hostapd_iface *iface);\n+void hostapd_deinit_ht(struct hostapd_iface *iface);\n+\n+#else\n+static inline void hostapd_deinit_ht(struct hostapd_iface *iface)\n+{\n+}\n+static inline void hostapd_trigger_20mhz(struct hostapd_iface *iface)\n+{\n+}\n+#endif /* CONFIG_IEEE80211N */\n+\n #endif /* IEEE802_11_H */\ndiff -purN hostapd-20130302/src/ap/ieee802_11_ht.c hostapd-20130302-linux/src/ap/ieee802_11_ht.c\n--- hostapd-20130302/src/ap/ieee802_11_ht.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/ieee802_11_ht.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -20,9 +20,11 @@\n #include \"drivers/driver.h\"\n #include \"hostapd.h\"\n #include \"ap_config.h\"\n+#include \"ap_drv_ops.h\"\n #include \"sta_info.h\"\n #include \"beacon.h\"\n #include \"ieee802_11.h\"\n+#include \"utils/eloop.h\"\n \n \n u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)\n@@ -70,12 +72,15 @@ u8 * hostapd_eid_ht_operation(struct hos\n \n \toper->control_chan = hapd->iconf->channel;\n \toper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);\n-\tif (hapd->iconf->secondary_channel == 1)\n-\t\toper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |\n-\t\t\tHT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;\n-\tif (hapd->iconf->secondary_channel == -1)\n-\t\toper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |\n-\t\t\tHT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;\n+\n+\tif (!hapd->iface->force_20mhz) {\n+\t\tif (hapd->iconf->secondary_channel == 1)\n+\t\t\toper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |\n+\t\t\t\tHT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;\n+\t\tif (hapd->iconf->secondary_channel == -1)\n+\t\t\toper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |\n+\t\t\t\tHT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;\n+\t}\n \n \tpos += sizeof(*oper);\n \n@@ -270,3 +275,84 @@ void hostapd_get_ht_capab(struct hostapd\n \n \tneg_ht_cap->ht_capabilities_info = host_to_le16(cap);\n }\n+\n+static void hostapd_set_force_20mhz(struct hostapd_iface *iface);\n+\n+static void hostapd_restore_40mhz(void *eloop_data, void *user_ctx)\n+{\n+\tstruct hostapd_iface *iface = eloop_data;\n+\tstruct os_time time;\n+\tint timeout;\n+\n+\tif (!iface->last_20mhz_trigger.sec)\n+\t    return;\n+\n+\tos_get_time(&time);\n+\ttimeout = iface->last_20mhz_trigger.sec + iface->conf->dynamic_ht40 -\n+\t\t  time.sec;\n+\n+\tif (timeout > 0) {\n+\t\teloop_register_timeout(timeout, 0, hostapd_restore_40mhz,\n+\t\t\t\t       iface, NULL);\n+\t\treturn;\n+\t}\n+\n+\tiface->last_20mhz_trigger.sec = 0;\n+\tiface->last_20mhz_trigger.usec = 0;\n+\n+\tiface->force_20mhz = 0;\n+\thostapd_set_force_20mhz(iface);\n+}\n+\n+static void hostapd_set_force_20mhz(struct hostapd_iface *iface)\n+{\n+\tint secondary_channel;\n+\tint i;\n+\n+\tieee802_11_set_beacons(iface);\n+\n+\tfor (i = 0; i < iface->num_bss; i++) {\n+\t\tstruct hostapd_data *hapd = iface->bss[i];\n+\n+\t\tif (iface->force_20mhz)\n+\t\t\tsecondary_channel = 0;\n+\t\telse\n+\t\t\tsecondary_channel = hapd->iconf->secondary_channel;\n+\n+\t\tif (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,\n+\t\t\t\t     hapd->iconf->channel,\n+\t\t\t\t     hapd->iconf->ieee80211n,\n+\t\t\t\t     hapd->iconf->ieee80211ac,\n+\t\t\t\t     secondary_channel,\n+\t\t\t\t     hapd->iconf->vht_oper_chwidth,\n+\t\t\t\t     hapd->iconf->vht_oper_centr_freq_seg0_idx,\n+\t\t\t\t     hapd->iconf->vht_oper_centr_freq_seg1_idx)) {\n+\t\t\twpa_printf(MSG_ERROR, \"Could not set channel for \"\n+\t\t\t\t   \"kernel driver\");\n+\t\t}\n+\t}\n+}\n+\n+void hostapd_deinit_ht(struct hostapd_iface *iface)\n+{\n+\teloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);\n+}\n+\n+void hostapd_trigger_20mhz(struct hostapd_iface *iface)\n+{\n+\tif (!iface->conf->dynamic_ht40)\n+\t\treturn;\n+\n+\tif (!iface->force_20mhz) {\n+\t\tiface->force_20mhz = 1;\n+\t\thostapd_set_force_20mhz(iface);\n+\t}\n+\n+\tif (!iface->last_20mhz_trigger.sec) {\n+\t\teloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);\n+\t\teloop_register_timeout(iface->conf->dynamic_ht40, 0,\n+\t\t\t\t       hostapd_restore_40mhz, iface, NULL);\n+\t}\n+\n+\tos_get_time(&iface->last_20mhz_trigger);\n+}\ndiff -purN hostapd-20130302/src/ap/ieee802_1x.c hostapd-20130302-linux/src/ap/ieee802_1x.c\n--- hostapd-20130302/src/ap/ieee802_1x.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/ieee802_1x.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -2043,11 +2043,12 @@ void ieee802_1x_notify_pre_auth(struct e\n }\n \n \n-static const char * bool_txt(Boolean bool)\n+static const char * bool_txt(Boolean bool_val)\n {\n-\treturn bool ? \"TRUE\" : \"FALSE\";\n+\treturn bool_val ? \"TRUE\" : \"FALSE\";\n }\n \n+#ifdef CONFIG_CTRL_IFACE_MIB\n \n int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)\n {\n@@ -2200,6 +2201,7 @@ int ieee802_1x_get_mib_sta(struct hostap\n \treturn len;\n }\n \n+#endif\n \n static void ieee802_1x_finished(struct hostapd_data *hapd,\n \t\t\t\tstruct sta_info *sta, int success)\ndiff -purN hostapd-20130302/src/ap/sta_info.c hostapd-20130302-linux/src/ap/sta_info.c\n--- hostapd-20130302/src/ap/sta_info.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/sta_info.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -576,7 +576,7 @@ void ap_sta_disassociate(struct hostapd_\n {\n \twpa_printf(MSG_DEBUG, \"%s: disassociate STA \" MACSTR,\n \t\t   hapd->conf->iface, MAC2STR(sta->addr));\n-\tsta->flags &= ~WLAN_STA_ASSOC;\n+\tsta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);\n \tap_sta_set_authorized(hapd, sta, 0);\n \tsta->timeout_next = STA_DEAUTH;\n \twpa_printf(MSG_DEBUG, \"%s: reschedule ap_handle_timer timeout \"\ndiff -purN hostapd-20130302/src/ap/wpa_auth.c hostapd-20130302-linux/src/ap/wpa_auth.c\n--- hostapd-20130302/src/ap/wpa_auth.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/wpa_auth.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -2687,6 +2687,7 @@ static const char * wpa_bool_txt(int boo\n \treturn bool ? \"TRUE\" : \"FALSE\";\n }\n \n+#ifdef CONFIG_CTRL_IFACE_MIB\n \n #define RSN_SUITE \"%02x-%02x-%02x-%d\"\n #define RSN_SUITE_ARG(s) \\\n@@ -2831,7 +2832,7 @@ int wpa_get_mib_sta(struct wpa_state_mac\n \n \treturn len;\n }\n-\n+#endif\n \n void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)\n {\ndiff -purN hostapd-20130302/src/ap/wps_hostapd.c hostapd-20130302-linux/src/ap/wps_hostapd.c\n--- hostapd-20130302/src/ap/wps_hostapd.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/ap/wps_hostapd.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -871,11 +871,9 @@ int hostapd_init_wps(struct hostapd_data\n \n \t\tif (conf->rsn_pairwise & WPA_CIPHER_CCMP)\n \t\t\twps->encr_types |= WPS_ENCR_AES;\n-\t\tif (conf->rsn_pairwise & WPA_CIPHER_TKIP)\n+\t\telse if (conf->rsn_pairwise & WPA_CIPHER_TKIP)\n \t\t\twps->encr_types |= WPS_ENCR_TKIP;\n-\t}\n-\n-\tif (conf->wpa & WPA_PROTO_WPA) {\n+\t} else if (conf->wpa & WPA_PROTO_WPA) {\n \t\tif (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)\n \t\t\twps->auth_types |= WPS_AUTH_WPAPSK;\n \t\tif (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)\n@@ -883,7 +881,7 @@ int hostapd_init_wps(struct hostapd_data\n \n \t\tif (conf->wpa_pairwise & WPA_CIPHER_CCMP)\n \t\t\twps->encr_types |= WPS_ENCR_AES;\n-\t\tif (conf->wpa_pairwise & WPA_CIPHER_TKIP)\n+\t\telse if (conf->wpa_pairwise & WPA_CIPHER_TKIP)\n \t\t\twps->encr_types |= WPS_ENCR_TKIP;\n \t}\n \ndiff -purN hostapd-20130302/src/capwap/capwap_mgmt_frame_ac.c hostapd-20130302-linux/src/capwap/capwap_mgmt_frame_ac.c\n--- hostapd-20130302/src/capwap/capwap_mgmt_frame_ac.c\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/capwap/capwap_mgmt_frame_ac.c\t2013-07-06 06:07:00.000000000 -0400\n@@ -0,0 +1,87 @@\n+#include \"utils/includes.h\"\n+\n+#include \"utils/common.h\"\n+#include \"radius/radius.h\"\n+#include \"drivers/driver.h\"\n+#include \"common/ieee802_11_defs.h\"\n+#include \"common/ieee802_11_common.h\"\n+#include \"common/wpa_ctrl.h\"\n+#include \"crypto/random.h\"\n+\n+\n+#define MAC_LENGTH 6\n+#define HLEN_80211 24\n+#define HLEN_LLC 8\n+\n+int same_mac( unsigned char *mac1, unsigned char *mac2){// return 0\n+\tint i;\n+\tfor(i=0;i<MAC_LENGTH;i++)if(mac1[i]!=mac2[i])return -1;\n+\treturn 0;\n+}\n+\n+int GetEapol_Frame( unsigned char *sa,  unsigned char *buf, int len){\n+\tstruct ieee80211_hdr *hdr;\n+\thdr = (struct ieee80211_hdr *) buf;\n+\tos_memcpy(sa, hdr->addr2, MAC_LENGTH);\n+\treturn HLEN_80211 + HLEN_LLC;\n+}\n+\n+int isEAPOL_Frame( unsigned char *buf, int len){\n+\tunsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n+\tint i;\n+\t\n+\tfor(i=0; i<6; i++)if(rfc1042_header[i]!=buf[i + HLEN_80211])return 0;\n+\treturn 1;\n+}\n+\n+void stampa_mac(char *s,  unsigned char *mac){\n+\tint i;\n+\twpa_printf(MSG_DEBUG,\"%s\",s);\n+\tfor(i=0; i<6; i++)wpa_printf(MSG_DEBUG,\"%02X \",mac[i]);\n+\twpa_printf(MSG_DEBUG,\"\\n\");\n+}\n+\n+void stamp_all_max( unsigned char *buf,  unsigned char *own_mac){\n+\tstruct ieee80211_hdr *hdr;\n+\t\n+\thdr = (struct ieee80211_hdr *) buf;\n+\n+\tstampa_mac(\"addr1 \",hdr->addr1);\n+\tstampa_mac(\"addr2 \",hdr->addr2);\n+\tstampa_mac(\"addr3 \",hdr->addr3);\n+\tstampa_mac(\"own_mac \", own_mac);\n+}\n+\n+int isCallBackFrame( unsigned char *buf, int len,  unsigned char *own_mac){\n+\t// return 1 if is it CALL Back Frame\n+\t// return 0 if is NOT CALL Back Frame\n+\tstruct ieee80211_hdr *hdr;\n+\tu16 fc;\n+\t\n+\thdr = (struct ieee80211_hdr *) buf;\n+\tfc = le_to_host16(hdr->frame_control);\n+\n+\tif( same_mac(hdr->addr2,own_mac)==0 && same_mac(hdr->addr3,own_mac)==0 )return 1;\n+\treturn 0;\n+}\n+\n+int AC_get_SubType( unsigned char *buf, int len){\n+\tstruct ieee80211_hdr *hdr;\n+\tu16 fc;\n+\t\n+\thdr = (struct ieee80211_hdr *) buf;\n+\tfc = le_to_host16(hdr->frame_control);\n+\t\n+\treturn WLAN_FC_GET_STYPE(fc);\n+}\n+\n+int AC_get_Type( unsigned char *buf, int len){\n+\tstruct ieee80211_hdr *hdr;\n+\tu16 fc;\n+\t\n+\thdr = (struct ieee80211_hdr *) buf;\n+\tfc = le_to_host16(hdr->frame_control);\n+\t\n+\treturn WLAN_FC_GET_TYPE(fc);\n+}\n+\ndiff -purN hostapd-20130302/src/capwap/capwap_mgmt_frame.h hostapd-20130302-linux/src/capwap/capwap_mgmt_frame.h\n--- hostapd-20130302/src/capwap/capwap_mgmt_frame.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/capwap/capwap_mgmt_frame.h\t2013-07-06 06:07:00.000000000 -0400\n@@ -0,0 +1,11 @@\n+#include \"drivers/driver.h\"\n+\n+int GetEapol_Frame( unsigned char *sa,  unsigned char *buf, int len);\n+\n+int isEAPOL_Frame( unsigned char *buf, int len);\n+\n+int isCallBackFrame( unsigned char *buf, int len,  unsigned char *own_mac);\n+\n+int AC_get_SubType( unsigned char *buf, int len);\n+\n+int AC_get_Type( unsigned char *buf, int len);\ndiff -purN hostapd-20130302/src/capwap/file_conf.h hostapd-20130302-linux/src/capwap/file_conf.h\n--- hostapd-20130302/src/capwap/file_conf.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/capwap/file_conf.h\t2013-07-07 13:07:40.000000000 -0400\n@@ -0,0 +1,121 @@\n+#define CONFIGFILE \"/etc/hostapd_ac.conf\"\n+#define VARLENGTH 1024 \n+\n+struct config_ac {\n+\tint ac_port;\n+\tchar ip_ac[50];\n+\tchar path_unix_socket[50];\n+}config_ac;\n+\n+int max_(int integer1,int integer2){\n+\tif(integer1>integer2)return integer1;\n+\treturn integer2;\n+}\n+\n+int countString(char string[]){\n+\tint cnt=0;\n+\tfor(cnt=0;string[cnt]!=0;cnt++);\n+\treturn cnt;\n+}\n+\n+int isEqualString(char String1[],char String2[]){\n+\tint len1=countString(String1);\n+\tint len2=countString(String2);\n+\tint i;\n+\tfor( i=0;i<max_(len1,len2);++i ){\n+\t\tif ( String1[i]==0 && String2[i]==0 )return 1;\n+\t\tif ( String1[i]==0 || String2[i]==0 )return 0;\n+\t\tif ( String1[i]!=String2[i] )return 0;\n+\t}\n+\treturn 1;\n+}\n+\n+int StartWith(char String1[],char String2[]){\n+\tint len1=countString(String1);\n+\tint len2=countString(String2);\n+\tint i;\n+\t\n+\tfor( i=0; i<len2;i++ ){\n+\n+\t\tif ( String1[i]!=String2[i] )return 0;\n+\t}\n+\n+\treturn 1;\n+}\n+\n+void ReplaceString(char *String1,char *rep,char *String2){\t\n+\tif(isEqualString(String1,rep)){\n+\t\tString1[0]=0;\n+\t\treturn;\n+\t}\n+\tif(String1[0]==0 || rep[0]==0)return;\n+\tint i,j,k,b,l,m;\n+\tchar tmp[strlen(String1)+strlen(String2)+1];\n+\tfor(i=0;i<=strlen(String1)+strlen(String2)-1;i++)tmp[i]=88;\n+\ttmp[i]=0;\n+\tfor(i=0;i<=strlen(String1)-1;i++){\n+\t\tif(strlen(rep)>=1)b=1;\n+\t\tfor(j=0;j<=strlen(rep)-1;j++){\n+\t\t\tif(String1[i+j]!=rep[j]){ \n+\t\t\t\tb=0; \n+\t\t\t\tbreak; \n+\t\t\t}\n+\t\t}\t\n+\t\tif(b){\n+\t\t\tfor(k=0;k<i;k++)tmp[k]=String1[k];\n+\t\t\tif(strlen(String2)>0){\n+\t\t\t\tfor(m=0;m<=strlen(String2)-1;++m,k++)tmp[k]=String2[m];\n+\t\t\t}\n+\t\t\tfor(l=i+j;l<=strlen(String1)-1;l++,k++)tmp[k]=String1[l];\n+\t\t\ttmp[k]=0;\n+\n+\t\t\tfor(k=0;k<strlen(tmp);k++)String1[k]=tmp[k];\n+\t\t\tif (String1[k-1]==10)String1[k-1]=0;\n+\t\t\telse \tString1[k]=0;\t\n+\t\t}\n+\t}\n+}\n+\n+void ReadConfiguration(struct config_ac *con_ac){\n+\tFILE *file;\n+\n+    file=fopen(CONFIGFILE,\"r\");\n+\n+\tchar ss[VARLENGTH];\n+\t\n+\tsprintf(con_ac->ip_ac,\"\");\n+\tsprintf(con_ac->path_unix_socket,\"\");\n+\tcon_ac->ac_port=0;\n+\n+\twhile(1){\n+\t\tif (fgets(ss,VARLENGTH,file)==NULL)break;\n+\t\tif(ss[0]=='\\r' || ss[0]=='\\n' || ss[0]=='#')continue;\n+\n+\t\tif(StartWith(ss,\"ip_daemon_ac\")){\n+\t\t\tReplaceString(ss, \"ip_daemon_ac\", \"\");\n+\t\t\tReplaceString(ss, \"=\", \"\");\n+\t\t\tReplaceString(ss, \"\\n\", \"\");\n+\t\t\tReplaceString(ss, \" \", \"\");\n+\t\t\tsprintf(con_ac->ip_ac, \"%s\", ss);\n+\t\t\t\n+\t\t}else if(StartWith(ss,\"sock_path_ac\")){\n+\t\t\tReplaceString(ss, \"sock_path_ac\", \"\");\n+\t\t\tReplaceString(ss, \"=\", \"\");\n+\t\t\tReplaceString(ss, \"\\n\", \"\");\n+\t\t\tReplaceString(ss, \" \", \"\");\n+\t\t\tsprintf(con_ac->path_unix_socket, \"%s\", ss);\n+\t\t\t\n+\t\t}else if(StartWith(ss,\"port_daemon_ac\")){\n+\t\t\tReplaceString(ss, \"port_daemon_ac\",\"\");\n+\t\t\tReplaceString(ss, \"\\n\", \"\");\n+\t\t\tReplaceString(ss, \" \", \"\");\n+\t\t\tReplaceString(ss, \"=\", \"\");\n+\t\t\tcon_ac->ac_port = atoi(ss);\n+\t\t}\n+\n+\t}\n+\tfclose(file);\n+\treturn;\n+}\n+\n+\ndiff -purN hostapd-20130302/src/capwap/ipc_capwap_ac.c hostapd-20130302-linux/src/capwap/ipc_capwap_ac.c\n--- hostapd-20130302/src/capwap/ipc_capwap_ac.c\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/capwap/ipc_capwap_ac.c\t2013-07-07 03:52:10.000000000 -0400\n@@ -0,0 +1,597 @@\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <errno.h>\n+#include <string.h>\n+#include <sys/types.h>\n+#include <sys/socket.h>\n+#include <netinet/in.h>\n+#include <sys/un.h>\n+#include \"eloop.h\"\n+#include \"utils/includes.h\"\n+\n+\n+#include \"utils/common.h\"\n+#include \"common/ieee802_11_defs.h\"\n+#include \"common/ieee802_11_common.h\"\n+#include \"drivers/driver.h\"\n+#include \"ap/hostapd.h\"\n+#include \"ap/ap_config.h\"\n+#include \"ap/ap_drv_ops.h\"\n+\n+#include \"file_conf.h\"\n+#include \"smac_code.h\"\n+#include \"ipc_capwap_ac.h\"\n+\n+#define MAX_BUF 3000\n+\n+//#define LOCALUDP\n+//#define NETUDP\n+//#define USEIPV6\n+\n+struct config_ac con_ac;\n+unsigned char wlan0_capa[21];\n+\n+int fd_con;\n+\n+\n+#if defined(LOCALUDP)\n+\tstruct sockaddr_un addr;\n+\tstruct sockaddr_un local;\n+\tint rn;\n+\t\n+#else\n+\t#if defined(USEIPV6)\n+\t\tstruct sockaddr_in6 client;\n+\t\tstruct sockaddr_in6 addr;\n+\t#else\n+\t\tstruct sockaddr_in client;\n+\t\tstruct sockaddr_in addr;\n+\t#endif\n+#endif\n+\n+#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))\n+#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))\n+#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))\n+\n+\n+\n+int address_size;\n+\n+int capability_is_A(){\n+\tif( CHECKBIT(wlan0_capa[8],1))return 1;\n+\telse return 0;\n+}\n+int capability_is_B(){\n+\tif( CHECKBIT(wlan0_capa[8],0))return 1;\n+\telse return 0;\n+}\n+int capability_is_G(){\n+\tif( CHECKBIT(wlan0_capa[8],2))return 1;\n+\telse return 0;\n+}\n+int capability_is_N(){\n+\tif( CHECKBIT(wlan0_capa[8],3))return 1;\n+\telse return 0;\n+}\n+\n+int capability_get_num_modes(){\n+\tint num_modes = 0;\n+\t\n+\tif( CHECKBIT(wlan0_capa[8],0)) num_modes++;\n+\tif( CHECKBIT(wlan0_capa[8],1)) num_modes++;\n+\tif( CHECKBIT(wlan0_capa[8],2)) num_modes++;\n+\tif( CHECKBIT(wlan0_capa[8],3)) num_modes++;\n+\t\n+\treturn num_modes;\n+}\n+\n+int capability_get_first_channel(){\n+\treturn (int)wlan0_capa[10];\n+}\n+\n+int capability_get_num_channels(){\n+\treturn (int)wlan0_capa[12];\n+}\n+\n+int capability_get_max_dBm(){\n+\treturn (int)wlan0_capa[14];\n+}\n+\n+int capability_get_rates(int *rate_arr){\n+\tint num_rates = 0;\n+\tint i;\n+\tfor(i=0; i<8; i++){\n+\t\tif( wlan0_capa[i]==0 ) continue;\n+\n+\t\tif( CHECKBIT(wlan0_capa[i],7) ){\n+\t\t\tCLEARBIT(wlan0_capa[i],7);\n+\t\t\trate_arr[num_rates] = (int)(wlan0_capa[i] * -5);\n+\t\t}else{\n+\t\t\trate_arr[num_rates] = (int)(wlan0_capa[i] * 5);\n+\t\t}\n+\t\tnum_rates++;\n+\t}\n+\treturn num_rates;\n+}\n+\n+void capability_get_mac(char *buf){\n+\tmemcpy(buf, wlan0_capa + 15, 6);\n+}\n+\n+void prep_beacon(int fd,struct hostapd_data *hapd,struct wpa_driver_ap_params *params){\n+\tstruct hostapd_data *h = hapd;\n+\tshort ssid_len = (short)h->conf->ssid.ssid_len;\n+\tshort key_len = (short) h->conf->ssid.wep.len[h->conf->ssid.wep.idx];\n+\t\n+\t\n+\twpa_printf(MSG_DEBUG,\"SSID: %s ssid_len:%d\\n\",h->conf->ssid.ssid,ssid_len);\n+\twpa_printf(MSG_DEBUG,\"IDX:%d   key_len:%d    key:%s  \\n\",h->conf->ssid.wep.idx,key_len,h->conf->ssid.wep.key[h->conf->ssid.wep.idx]);\n+\n+\tunsigned char A1 = 0;\n+\tunsigned char A2 = 0;\n+\t\n+\tSETBIT(A1,7); \t//E (ESS)\n+\tCLEARBIT(A1,6); //I (IBSS)\n+\tCLEARBIT(A1,5); //C (CF Pollable)\n+\tCLEARBIT(A1,4); //F (CF Pollable Request)\n+\tif(params->privacy)\t\tSETBIT(A1,3); //P (Privacy)\n+\telse\t\t\t\t\tCLEARBIT(A1,3); //P (Privacy)\n+\tif(params->preamble)\tSETBIT(A1,2); //S (Sort Preamble)\n+\telse    \t\t\t\tCLEARBIT(A1,2); //S (Sort Preamble)\n+\tCLEARBIT(A1,1); //B (PBCC)\n+\tCLEARBIT(A1,0); //A (Channel Agility)\n+\t\n+\tCLEARBIT(A2,7); //I (IBSS)\n+\tCLEARBIT(A2,6); //I (IBSS)\n+\tif(params->short_slot_time)\t\tSETBIT(A2,5); //I (IBSS)\n+\telse  \t\t\t\t\t\t\tCLEARBIT(A2,5); //I (IBSS)\n+\tCLEARBIT(A2,4); //I (IBSS)\n+\tCLEARBIT(A2,3); //I (IBSS)\n+\tCLEARBIT(A2,2); //I (IBSS)\n+\tCLEARBIT(A2,1); //I (IBSS)\n+\tCLEARBIT(A2,0); //I (IBSS)\n+\t\n+\n+\n+\tint tot_len = 19 + ssid_len + key_len;\n+\t\n+\t\n+\tunsigned char buf[tot_len];\n+\t\n+\twpa_printf(MSG_DEBUG,\"Tot Len:%d \\n\",tot_len);\n+\t\n+\tbuf[0] = 0; // Radio ID\n+\tbuf[1] = 0; // WLAN ID\n+\tbuf[2] = A1; // Flags Part1\n+\tbuf[3] = A2;  // Flags Part2\n+\t\n+\tbuf[4] = h->conf->ssid.wep.idx;  // Key Index\n+\t\n+\tif(params->privacy)\tbuf[5] = 1;  // Key Status\n+\telse \t\t\t\tbuf[5] = 0;  // Key Status\n+\t\n+\twpa_printf(MSG_DEBUG,\"keylen: %d \\n\",key_len);\n+\t\n+\t\n+\t//memcpy(buf+6, &key_len, 1);\n+\t//memcpy(buf+7, &key_len, 1);\n+\tif (key_len > 0){\n+\tbuf[6] = *(&key_len + 1);  // Key Length Part1\n+\tbuf[7] = *(&key_len + 0);  // Key Length Part2\n+\t}\n+\telse {\n+\tbuf[6] = *(&key_len + 0);\n+\tbuf[7] = *(&key_len + 0);\n+\t}\n+\n+\twpa_printf(MSG_DEBUG,\"keylen: %d %02X %02X \\n\",key_len,buf[6],buf[7]);\n+\t\n+\tif( key_len ) memcpy( buf + 8, h->conf->ssid.wep.key[h->conf->ssid.wep.idx], key_len);\n+\t\n+\tbuf[8+key_len] = 0;   // Group TSC Part1\n+\tbuf[9+key_len] = 0;   // Group TSC Part2\n+\tbuf[10+key_len] = 0;  // Group TSC Part3\n+\tbuf[11+key_len] = 0;  // Group TSC Part4\n+\t\n+\tbuf[12+key_len] = 0;  // Group TSC Part5\n+\tbuf[13+key_len] = 0;  // Group TSC Part6\n+\tbuf[14+key_len] = 0;  // QoS\n+\t\n+\tif(params->privacy)\tbuf[15+key_len] = 1;  // Auth Type\n+\telse \t\t\t\tbuf[15+key_len] = 0;  // Auth Type\n+\t\n+\tbuf[16+key_len] = 1;  // Mac Mode\n+\tbuf[17+key_len] = 2;  // Tunnel Mode\n+\tbuf[18+key_len] = 1;  // Suppress SSID\n+\t\n+\tmemcpy(buf + key_len + 19, h->conf->ssid.ssid, ssid_len);\n+\t\n+\tint i;\n+\tfor(i=0; i<tot_len; i++){\n+\t\tif((i%4)==0)printf(\"\\n\");\n+\t\twpa_printf(MSG_DEBUG,\"%02X \",buf[i]);\n+\t}\n+\twpa_printf(MSG_DEBUG,\"\\n\");\n+\t\n+\tsend_response(fd, ADD_WLAN, buf, tot_len);\n+}\n+\n+void ipc_send_ADD_WLAN(int fd,char *ssid, int len){\n+\n+\tint new_len = 19 + len;\n+\tunsigned char cmd[new_len];\n+\t\n+\t\n+\tint i;\n+\tfor(i=0; i<new_len; i++)cmd[i]=0;\n+\t\n+\tcmd[0] = 0; // Radio ID\n+\tcmd[1] = 0; // WLAN ID\n+\tcmd[2] = 128; // Flags Part1\n+\tcmd[3] = 0;  // Flags Part2\n+\t\n+\tcmd[4] = 0;  // Key Index\n+\tcmd[5] = 0;  // Key Status\n+\tcmd[6] = 0;  // Key Length Part1\n+\tcmd[7] = 0;  // Key Length Part2\n+\t\n+\tcmd[8] = 0;   // Group TSC Part1\n+\tcmd[9] = 0;   // Group TSC Part2\n+\tcmd[10] = 0;  // Group TSC Part3\n+\tcmd[11] = 0;  // Group TSC Part4\n+\t\n+\tcmd[12] = 0;  // Group TSC Part5\n+\tcmd[13] = 0;  // Group TSC Part6\n+\tcmd[14] = 0;  // QoS\n+\tcmd[15] = 0;  // Auth Type\n+\t\n+\tcmd[16] = 1;  // Mac Mode\n+\tcmd[17] = 2;  // Tunnel Mode\n+\tcmd[18] = 1;  // Suppress SSID\n+\t\n+\t\n+\tmemcpy(cmd+19, ssid, len);\n+\t\n+\tsend_response(fd, ADD_WLAN, cmd, new_len);\n+}\n+\n+\n+void ipc_send_DEL_WLAN(int fd){\n+\tunsigned char cmd[2];\n+\n+\tcmd[0] = 0; // Radio ID\n+\tcmd[1] = 0; // WLAN ID\n+\twpa_printf(MSG_DEBUG,\"DEL 1\\n\");\n+\tsend_response(fd, DEL_WLAN, cmd, 2);\n+}\n+\n+void ipc_send_CLOSE_to_AC(int fd){\n+\tchar cmd[10];\n+\tsend_response(fd, CLOSE, cmd, 10);\n+}\n+\n+void ipc_send_add_station(int fd, u8 *buf, int len){\n+\tu16 fc;\n+\tint status = -1;\n+\tunsigned char cmd[6];\n+\tstruct ieee80211_mgmt *mgmt;\n+\tstruct ieee80211_hdr *hdr;\n+\tmgmt = (struct ieee80211_mgmt *) buf;\n+\thdr = (struct ieee80211_hdr *) buf;\n+\t\n+\tfc = le_to_host16(hdr->frame_control);\n+\t\n+\tif( WLAN_FC_GET_STYPE(fc)==WLAN_FC_STYPE_ASSOC_RESP ){\n+\t\tstatus = le_to_host16(mgmt->u.assoc_resp.status_code);\n+\t\t\n+\t}else if( WLAN_FC_GET_STYPE(fc)==WLAN_FC_STYPE_REASSOC_RESP){\n+\t\tstatus = le_to_host16(mgmt->u.reassoc_resp.status_code);\n+\t\t\n+\t}else{\n+\t\twpa_printf(MSG_ERROR, \"Error: ipc_send_add_station\\n\");\n+\t\treturn;\n+\t}\n+\t\n+\tif(status == 0){\n+\t\tmemcpy(cmd,mgmt->da,6);\n+\t\tsend_response(fd, SET_ADDR, cmd, 6);\n+\t}\n+\t\n+\t\n+}\n+\n+void ipc_send_del_station(int fd, u8 *buf, int len){\n+\tu16 fc;\n+\tunsigned char cmd[6];\n+\tstruct ieee80211_hdr *hdr;\n+\thdr = (struct ieee80211_hdr *) buf;\n+\t\n+\tfc = le_to_host16(hdr->frame_control);\n+\t\n+\tif( WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_DISASSOC ){\n+\t\twpa_printf(MSG_DEBUG,\"Il pacchetto non e' di tipo DISASSOC\\n\");\n+\t\treturn;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG,\"DEL ADDR: %02X %02X %02X %02X %02X %02X \\n\",hdr->addr2[0],hdr->addr2[1],hdr->addr2[2],hdr->addr2[3],hdr->addr2[4],hdr->addr2[5]);\n+\n+\tmemcpy(cmd,hdr->addr2,6);\n+\tsend_response(fd, DEL_ADDR, cmd, 6);\n+\n+}\n+\n+void ipc_send_80211_to_wtp(int fd, u8 *buf, int len){\n+\t\n+\tsend_response(fd, DATE_TO_WTP, buf, len);\n+}\n+\n+void send_response(int fd, u8 code, u8 *buf, int len){\n+\tu8 tmp_buf[MAX_BUF];\n+\ttmp_buf[0] = code;\n+\t\n+\tint n;\n+\t\n+\t#if defined(LOCALUDP)\n+\t\tsprintf(tmp_buf + 1, \"%05d\", rn);\n+\t\tmemcpy(tmp_buf + 6, buf, len);\n+\t\tn = sendto(fd, tmp_buf, len + 6, 0, (struct sockaddr *)&addr, address_size);\n+\t#else\n+\t\tmemcpy(tmp_buf + 1, buf, len);\n+\t\tn = sendto(fd, tmp_buf, len + 1, 0, (struct sockaddr *)&addr, address_size);\n+\t#endif\n+\t\n+\n+\tif ( n < 0 ) {\n+\t\tperror(\"send\");\n+\t\treturn;\n+\t}\n+\t\n+}\n+\n+\n+void management_recv(int fd, u8 code, u8 *buf, int len, void *hapd, void *inject_func){\n+\n+\tif(code == PING){\n+\t\tsend_response(fd, PONG, buf, len);\n+\t\t\n+\t}else if( code==DATE_TO_AC ){\n+\t\tstruct hostapd_data *h = hapd;\n+\t\tvoid (*pointer_inject_frame_in_hostapd) (void*,unsigned char*,int);\n+\t\tpointer_inject_frame_in_hostapd = inject_func;\n+\t\tpointer_inject_frame_in_hostapd(h->drv_priv, buf, len);\n+\t\t//hostapd_inject_frame_in_hostapd(h, buf, len);\n+\t\t\n+\t}else{\n+\t\twpa_printf(MSG_DEBUG,\"ERROR IPC: received unrecognizedcode: %d\\n\",code);\n+\t}\n+\n+}\n+\n+void recv_request(int fd,void *hapd, void *inject_func){\n+\tchar str[MAX_BUF];\n+\n+\tint n;\n+\t\n+\t#if defined(LOCALUDP)\n+\t\tn = recvfrom(fd, str, MAX_BUF, 0, (struct sockaddr *)&local, &address_size);\n+\t#else\n+\t\tn = recvfrom(fd, str, MAX_BUF, 0, (struct sockaddr *)&addr, &address_size);\n+\t#endif\n+\t\n+\n+    if(n<=0){\n+\t\tend_ipc(fd);\n+\t\treturn;\n+\t}\n+\t\n+\t\t\n+\tmanagement_recv(fd, str[0], str + 1, n -1, hapd, inject_func);\t\n+}\n+\n+\n+\n+int open_socket(){\n+\t\n+\t\n+\tint fd_ac, n, con_res;\n+\t\n+\tchar buffer[100];\n+\t\n+\t#if defined(LOCALUDP)\n+\t\tsrand((unsigned)time(0));\n+\t\tfd_ac = socket(AF_UNIX, SOCK_DGRAM, 0);\n+\t\t\n+\t#elif defined(NETUDP)\n+\t\t#if defined(USEIPV6)\n+\t\t\tfd_ac = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);\n+\t\t#else\n+\t\t\tfd_ac = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n+\t\t#endif\t\n+\t\t\n+\t#else\n+\t\t#if defined(USEIPV6)\n+\t\t\tfd_ac = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);\n+\t\t#else\n+\t\t\tfd_ac = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);\n+\t\t#endif\n+\n+\t#endif\n+\t\n+\t#if defined(LOCALUDP)\n+\t\taddr.sun_family = AF_UNIX;\n+\t\tstrcpy(addr.sun_path, con_ac.path_unix_socket);\n+\t\tlocal.sun_family = AF_UNIX;\n+\t\t\n+\t\twhile(1){\n+\t\t\trn = rand()%100000;\n+\t\t\tsprintf(local.sun_path, \"%s%05d\", con_ac.path_unix_socket, rn);\n+\t\t\tif( bind(fd_ac, (struct sockaddr *)&local, strlen(local.sun_path) + sizeof(local.sun_family))==-1){\n+\t\t\t\tsleep(1); \n+\t\t\t\tcontinue; \n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\twpa_printf(MSG_DEBUG,\"Connect to %s from %s\\n\",addr.sun_path, local.sun_path);\t\t\t\t\n+\t\t\t\n+\t#else\n+\t\t#if defined(USEIPV6)\n+\t\t\taddr.sin6_family = AF_INET6;\n+\t\t\taddr.sin6_port = con_ac.ac_port;\n+\t\t\tinet_pton(AF_INET6, con_ac.ip_ac, &addr.sin6_addr);\n+\t\t#else\n+\t\t\taddr.sin_family = AF_INET;\n+\t\t\taddr.sin_port = htons(con_ac.ac_port);\n+\t\t\taddr.sin_addr.s_addr = inet_addr(con_ac.ip_ac);\n+\t\t\t\n+\t\t#endif\n+\n+\t\twpa_printf(MSG_DEBUG,\"Try connecting to %s:%d\\n\",con_ac.ip_ac, con_ac.ac_port);\n+\t\t\n+\t#endif\n+\t\n+\taddress_size = sizeof(addr);\n+\n+\n+\t\t\n+\twhile(1){\n+\t\t#if defined(LOCALUDP)\n+\t\t\tsprintf(buffer,\"Z%05dconnect\",rn);\n+\t\t#else\n+\t\t\tsprintf(buffer,\"Zconnect\");\n+\t\t#endif\n+\t\t\n+\t\tbuffer[0] = CONNECT;\n+\t\t\n+\t\tn = sendto(fd_ac, buffer, strlen(buffer), 0, (struct sockaddr *)&addr, address_size);\n+  \n+\t\t#if defined(LOCALUDP)\n+\t\t\tn = recvfrom(fd_ac, buffer, sizeof(buffer), 0, (struct sockaddr *)&local, &address_size);\n+\t\t#else\n+\t\t\tn = recvfrom(fd_ac, buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &address_size);\n+\t\t#endif\n+\t\tif(buffer[0] == CONNECT_R){\n+\t\t\twpa_printf(MSG_DEBUG,\"CONNECTED!!!\");\n+\t\t\tbreak;\n+\n+\t\t}else{\n+\t\t\tsleep(3);\n+\t\t\t\n+\t\t}\n+\t}\n+\t\n+    return fd_ac;\n+}\n+\n+\n+void wait_capability_from_AC(int fd, void *hapd){\n+\tunsigned char buffer[10];\n+\tint n;\n+\t\n+\tsleep(0.5);\n+\t\n+\twhile(1){\n+\t\t\n+\t\t#if defined(LOCALUDP)\n+\t\t\tsprintf(buffer,\"X%05d\",rn);\n+\t\t#else\n+\t\t\tsprintf(buffer,\"X\");\n+\t\t#endif\n+\t\t\n+\t\tbuffer[0] = WANT_GOLIVE;\n+\t\tn = sendto(fd, buffer, strlen(buffer), 0, (struct sockaddr *)&addr, address_size);\n+  \n+\n+\n+\t\t#if defined(LOCALUDP)\n+\t\t\tn = recvfrom(fd, buffer, 10, 0, (struct sockaddr *)&local, &address_size);\n+\t\t#else\n+\t\t\tn = recvfrom(fd, buffer, 10, 0, (struct sockaddr *)&addr, &address_size);\n+\t\t#endif\n+\t\n+\t\tif(n<=0){\n+\t\t\tend_ipc(fd);\n+\t\t\treturn;\n+\t\t}\n+\t\t\n+\t\tif(buffer[0] == SET_WTPRINFO){\n+\t\t\twpa_printf(MSG_DEBUG,\"SET_WTPRINFO: %02X\\n\",buffer[1]);\n+\t\t\tmemcpy( wlan0_capa+8, buffer+1, 1);\n+\t\t\tsend_response(fd, SET_WTPRINFO_R, NULL, 0);\n+\t\t\t\n+\t\t}else if(buffer[0] == SET_RATES){\n+\t\t\twpa_printf(MSG_DEBUG,\"SET_RATES: %02X %02X %02X %02X %02X %02X %02X %02X\\n\",buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],buffer[8]);\n+\t\t\tmemcpy( wlan0_capa, buffer+1, 8);\n+\t\t\tsend_response(fd, SET_RATES_R, NULL, 0);\n+\t\t\t\n+\t\t}else if(buffer[0] == SET_MDC){\n+\t\t\twpa_printf(MSG_DEBUG,\"SET_MDC: %02X %02X %02X %02X %02X %02X\\n\",buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6]);\n+\t\t\tmemcpy( wlan0_capa+9, buffer+1, 6);\n+\t\t\tsend_response(fd, SET_MDC_R, NULL, 0);\n+\t\t\t\n+\t\t}else if(buffer[0] == SET_MAC){\n+\t\t\twpa_printf(MSG_DEBUG,\"SET_MAC: %02X %02X %02X %02X %02X %02X\\n\",buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6]);\n+\t\t\tmemcpy( wlan0_capa+15, buffer+1, 6);\n+\t\t\tsend_response(fd, SET_MAC_R, NULL, 0);\n+\t\t\t\n+\t\t}else if(buffer[0] == GOLIVE){\n+\t\t\twpa_printf(MSG_DEBUG,\"GOLIVE:\\n\");\n+\t\t\tsend_response(fd, GOLIVE_R, NULL, 0);\n+\t\t\tbreak;\n+\t\t\t\n+\t\t}else if(buffer[0] == HAVE_TO_WAIT){\n+\t\t\twpa_printf(MSG_DEBUG,\"WAIT\");\n+\t\t\tsleep(1);\n+\t\t\n+\t\t}else if(buffer[0] == CLOSE){\n+\t\t\twpa_printf(MSG_DEBUG,\"CLOSE\");\n+\t\t\tend_ipc(fd);\n+\t\t\t\n+\t\t}else{\n+\t\t\twpa_printf(MSG_DEBUG,\"Unknow code (%d) received in CONNECTed Fase\\n\",buffer[0]);\n+\t\t}\n+\t}\n+\t\n+}\n+\n+int end_ipc(int fd){\n+\t\n+\tipc_send_CLOSE_to_AC(fd);\n+\tif(fd>=0){\n+\t\teloop_unregister_read_sock(fd);\n+\t\tif(close(fd)<0 ){\n+\t\t\t\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\t\n+\tif(\tfd_con>=0 ){\n+\t\tif(close(fd_con)<0 ){\n+\t\t\t\n+\t\t}\n+\t}\n+\t\n+\treturn 0;\n+}\n+\n+int start_ipc(void *hapd,void *inject_func){\n+\tReadConfiguration(&con_ac);\n+\twpa_printf(MSG_DEBUG,\"< DISCONNECTED >\\n\");\n+\t\n+\tint sockfd = open_socket();\n+\twpa_printf(MSG_DEBUG,\"< CONNECTED >\\n\");\n+\t\n+\twait_capability_from_AC(sockfd, hapd);\n+\twpa_printf(MSG_DEBUG,\"< LIVE >\\n\");\n+\t\n+\n+\tif(sockfd){\n+\t\tif (eloop_register_read_sock(sockfd, recv_request, hapd, inject_func)) {\n+\t\t\twpa_printf(MSG_ERROR, \"Clould not register IPC socket start_ipc\");\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\t\n+\treturn sockfd;\n+}\n+\n+\ndiff -purN hostapd-20130302/src/capwap/ipc_capwap_ac.h hostapd-20130302-linux/src/capwap/ipc_capwap_ac.h\n--- hostapd-20130302/src/capwap/ipc_capwap_ac.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/capwap/ipc_capwap_ac.h\t2013-07-07 03:54:59.000000000 -0400\n@@ -0,0 +1,7 @@\n+void ipc_send_80211_to_wtp(int fd, u8 *buf, int len);\n+\n+int start_ipc(void *hapd,void *inject_func);\n+\n+int end_ipc(int fd);\n+\n+void send_response(int fd, u8 code, u8 *buf, int len);\ndiff -purN hostapd-20130302/src/capwap/Makefile hostapd-20130302-linux/src/capwap/Makefile\n--- hostapd-20130302/src/capwap/Makefile\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/capwap/Makefile\t2013-07-06 07:04:12.000000000 -0400\n@@ -0,0 +1,8 @@\n+all:\n+\t@echo Nothing to be made.\n+\n+clean:\n+\trm -f *~ *.o *.d\n+\n+install:\n+\t@echo Nothing to be made.\ndiff -purN hostapd-20130302/src/capwap/smac_code.h hostapd-20130302-linux/src/capwap/smac_code.h\n--- hostapd-20130302/src/capwap/smac_code.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/capwap/smac_code.h\t2013-07-06 06:07:00.000000000 -0400\n@@ -0,0 +1,107 @@\n+#include <linux/types.h>\n+\n+unsigned char ERROR = 0;\n+\n+unsigned char CLOSE = 1;\n+\n+unsigned char PING = 2; //  [2]ping\n+unsigned char PONG = 3;//  [3]pong\n+\n+unsigned char START_WLAN = 4;\n+unsigned char START_WLAN_R = 5;\n+\n+unsigned char STOP_WLAN = 6;\n+unsigned char STOP_WLAN_R = 7;\n+\n+unsigned char SET_FREQ = 8; // FREQ sec_channel_offset ht_enabled channel MODE  ex. \"[8]2462 0 0 11 0\"\n+unsigned char SET_FREQ_R = 9; // 0 or 1  ex. \"[9]0\"\n+\n+unsigned char GET_FREQ = 10; // ex. \"[10]\"\n+unsigned char GET_FREQ_R = 11; // ex. \"[11]2462 0 0 11 0\"\n+\n+unsigned char SET_FRAG = 12; // Typically the range used for fragmentation threshold is 256-2346 (-1 == off) ex. \"[12]2000\"\n+unsigned char SET_FRAG_R = 13;// ex. \"[13]0\"\n+\n+unsigned char GET_FRAG = 14; // ex. \"[14]\"   (-1 == off)\n+unsigned char GET_FRAG_R = 15; // ex. \"[15]2000\" \n+\n+unsigned char SET_BITRATE = 16; \n+unsigned char SET_BITRATE_R = 17;\n+\n+unsigned char GET_BITRATE = 18; \n+unsigned char GET_BITRATE_R = 19; \n+\n+unsigned char SET_RTS = 20; // 0-2347 (-1 == off)  ex. \"[20]100\"  (-1 == off)\n+unsigned char SET_RTS_R = 21;// ex. \"[21]0\"\n+\n+unsigned char GET_RTS = 22; // ex. \"]22]\"  (-1 == off)\n+unsigned char GET_RTS_R = 23; // ex. \"[23]100\"\n+\n+unsigned char SET_TXPOWER = 24; \n+unsigned char SET_TXPOWER_R = 25;\n+\n+unsigned char GET_TXPOWER = 26; \n+unsigned char GET_TXPOWER_R = 27;\n+\n+/*\n+ * VO - 0  CWMIN:3  CWMAX:7  AIFS:2\n+ * VI - 1  CWMIN:7  CWMAX:15  AIFS:2\n+ * BE - 2  CWMIN:15  CWMAX:1023  AIFS:3\n+ * BK - 3  CWMIN:15  CWMAX:1023  AIFS:7\n+ */\n+unsigned char SET_TXQ = 28; \n+unsigned char SET_TXQ_R = 29; \n+\n+unsigned char GET_TXQ = 30; \n+unsigned char GET_TXQ_R = 31;\n+\n+unsigned char SET_ADDR = 32;\n+unsigned char SET_ADDR_R = 33;\n+\n+unsigned char DEL_ADDR = 34;\n+unsigned char DEL_ADDR_R = 35;\n+\n+unsigned char ADD_WLAN = 36;\n+unsigned char ADD_WLAN_R = 37;\n+\n+unsigned char DEL_WLAN = 38;\n+unsigned char DEL_WLAN_R = 39;\n+\n+unsigned char WTPRINFO = 40;\n+unsigned char WTPRINFO_R = 41;\n+\n+unsigned char GET_RATES = 42;\n+unsigned char GET_RATES_R = 43;\n+\n+unsigned char GET_MDC = 44;\n+unsigned char GET_MDC_R = 45;\n+\n+unsigned char SET_WTPRINFO = 46;\n+unsigned char SET_WTPRINFO_R = 47;\n+\n+unsigned char SET_RATES = 48;\n+unsigned char SET_RATES_R = 49;\n+\n+unsigned char SET_MDC = 50;\n+unsigned char SET_MDC_R = 51;\n+\n+unsigned char GOLIVE = 52;\n+unsigned char GOLIVE_R = 53;\n+\n+unsigned char WANT_GOLIVE = 54;\n+unsigned char HAVE_TO_WAIT = 55;\n+\n+unsigned char GET_MAC = 56;\n+unsigned char GET_MAC_R = 57;\n+\n+unsigned char SET_MAC = 58;\n+unsigned char SET_MAC_R = 59;\n+\n+unsigned char DATE_TO_WTP = 100;\n+unsigned char DATE_TO_AC = \t101;\n+\n+unsigned char CONNECT = 102;\n+unsigned char CONNECT_R = 103;\n+\n+unsigned char GOWAITWLAN = 104;\n+unsigned char GOWAITWLAN_R = 105;\ndiff -purN hostapd-20130302/src/common/wpa_common.c hostapd-20130302-linux/src/common/wpa_common.c\n--- hostapd-20130302/src/common/wpa_common.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/common/wpa_common.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -965,6 +965,31 @@ const char * wpa_key_mgmt_txt(int key_mg\n }\n \n \n+static void wpa_fixup_wpa_ie_rsn(u8 *assoc_ie, const u8 *wpa_msg_ie,\n+\t\t\t\t size_t rsn_ie_len)\n+{\n+\tint pos, count;\n+\n+\tpos = sizeof(struct rsn_ie_hdr) + RSN_SELECTOR_LEN;\n+\tif (rsn_ie_len < pos + 2)\n+\t\treturn;\n+\n+\tcount = WPA_GET_LE16(wpa_msg_ie + pos);\n+\tpos += 2 + count * RSN_SELECTOR_LEN;\n+\tif (rsn_ie_len < pos + 2)\n+\t\treturn;\n+\n+\tcount = WPA_GET_LE16(wpa_msg_ie + pos);\n+\tpos += 2 + count * RSN_SELECTOR_LEN;\n+\tif (rsn_ie_len < pos + 2)\n+\t\treturn;\n+\n+\tif (!assoc_ie[pos] && !assoc_ie[pos + 1] &&\n+\t    (wpa_msg_ie[pos] || wpa_msg_ie[pos + 1]))\n+\t\tmemcpy(&assoc_ie[pos], &wpa_msg_ie[pos], 2);\n+}\n+\n+\n int wpa_compare_rsn_ie(int ft_initial_assoc,\n \t\t       const u8 *ie1, size_t ie1len,\n \t\t       const u8 *ie2, size_t ie2len)\n@@ -972,8 +997,19 @@ int wpa_compare_rsn_ie(int ft_initial_as\n \tif (ie1 == NULL || ie2 == NULL)\n \t\treturn -1;\n \n-\tif (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)\n-\t\treturn 0; /* identical IEs */\n+\tif (ie1len == ie2len) {\n+\t\tu8 *ie_tmp;\n+\n+\t\tif (os_memcmp(ie1, ie2, ie1len) == 0)\n+\t\t\treturn 0; /* identical IEs */\n+\n+\t\tie_tmp = alloca(ie1len);\n+\t\tmemcpy(ie_tmp, ie1, ie1len);\n+\t\twpa_fixup_wpa_ie_rsn(ie_tmp, ie2, ie1len);\n+\n+\t\tif (os_memcmp(ie_tmp, ie2, ie1len) == 0)\n+\t\t\treturn 0; /* only mismatch in RSN capabilties */\n+\t}\n \n #ifdef CONFIG_IEEE80211R\n \tif (ft_initial_assoc) {\ndiff -purN hostapd-20130302/src/drivers/capwap_copy.h hostapd-20130302-linux/src/drivers/capwap_copy.h\n--- hostapd-20130302/src/drivers/capwap_copy.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/capwap_copy.h\t2013-07-06 06:06:45.000000000 -0400\n@@ -0,0 +1,9 @@\n+enum capwap_iftype {\n+\tADHOC,\n+\tSTATION,\n+\tAP,\n+\tMONITOR,\n+\tP2P_CLIENT,\n+\tP2P_GO\n+};\n+\ndiff -purN hostapd-20130302/src/drivers/driver_capwap.c hostapd-20130302-linux/src/drivers/driver_capwap.c\n--- hostapd-20130302/src/drivers/driver_capwap.c\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/driver_capwap.c\t2013-07-07 03:56:47.000000000 -0400\n@@ -0,0 +1,9603 @@\n+/*\n+ * Driver interaction with Linux capwap/cfg80211\n+ * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>\n+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.\n+ * Copyright (c) 2005-2006, Devicescape Software, Inc.\n+ * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>\n+ * Copyright (c) 2009-2010, Atheros Communications\n+ *\n+ * This software may be distributed under the terms of the BSD license.\n+ * See README for more details.\n+ */\n+\n+#include \"includes.h\"\n+#include <sys/ioctl.h>\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <fcntl.h>\n+#include <net/if.h>\n+#include <netlink/genl/genl.h>\n+#include <netlink/genl/family.h>\n+#include <netlink/genl/ctrl.h>\n+#include <linux/rtnetlink.h>\n+#include <netpacket/packet.h>\n+#include <linux/filter.h>\n+#include <string.h>\n+#include <unistd.h>\n+#include <stdio.h>\n+#include <sys/socket.h>\n+#include <netinet/ip.h>\n+#include <netinet/ip_icmp.h>\n+#include <netinet/in.h>\n+#include <arpa/inet.h>\n+#include <netdb.h>\n+#include <linux/errqueue.h>\n+#include \"nl80211_copy.h\"\n+#include \"capwap_copy.h\"\n+\n+#include \"common.h\"\n+#include \"eloop.h\"\n+#include \"utils/list.h\"\n+#include \"common/ieee802_11_defs.h\"\n+#include \"common/ieee802_11_common.h\"\n+#include \"l2_packet/l2_packet.h\"\n+#include \"capwap/capwap_mgmt_frame.h\"\n+#include \"capwap/ipc_capwap_ac.h\"\n+#include \"netlink_fake.h\"\n+#include \"linux_ioctl_fake.h\"\n+#include \"radiotap.h\"\n+#include \"radiotap_iter.h\"\n+#include \"rfkill.h\"\n+#include \"driver.h\"\n+\n+#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))\n+#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))\n+#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))\n+\n+#define BUFFER_SIZE 65000\n+\n+struct ac_info {\n+       const char *pseudo_interface;\n+       char *eth_interface;\n+       char own_mac_addr[ETH_ALEN];\n+       int fd_ipc;\n+};\n+\n+struct ac_info generic_ac_info;\n+void AC_inject_frame_in_hostapd(void *priv, u8 *buf, int len);\n+\n+\n+#ifndef SO_WIFI_STATUS\n+# if defined(__sparc__)\n+#  define SO_WIFI_STATUS\t0x0025\n+# elif defined(__parisc__)\n+#  define SO_WIFI_STATUS\t0x4022\n+# else\n+#  define SO_WIFI_STATUS\t41\n+# endif\n+\n+# define SCM_WIFI_STATUS\tSO_WIFI_STATUS\n+#endif\n+\n+#ifndef SO_EE_ORIGIN_TXSTATUS\n+#define SO_EE_ORIGIN_TXSTATUS\t4\n+#endif\n+\n+#ifndef PACKET_TX_TIMESTAMP\n+#define PACKET_TX_TIMESTAMP\t16\n+#endif\n+\n+#ifdef ANDROID\n+#include \"android_drv.h\"\n+\n+/* system/core/libnl_2 in AOSP does not include nla_put_u32() */\n+int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)\n+{\n+\treturn nla_put(msg, attrtype, sizeof(uint32_t), &value);\n+}\n+#endif /* ANDROID */\n+#ifdef CONFIG_LIBNL20\n+/* libnl 2.0 compatibility code */\n+#define nl_handle nl_sock\n+#define capwap_handle_alloc nl_socket_alloc_cb\n+#define capwap_handle_destroy nl_socket_free\n+#else\n+/*\n+ * libnl 1.1 has a bug, it tries to allocate socket numbers densely\n+ * but when you free a socket again it will mess up its bitmap and\n+ * and use the wrong number the next time it needs a socket ID.\n+ * Therefore, we wrap the handle alloc/destroy and add our own pid\n+ * accounting.\n+ */\n+static uint32_t port_bitmap[32] = { 0 };\n+\n+static struct nl_handle *capwap_handle_alloc(void *cb)\n+{\n+\tstruct nl_handle *handle;\n+\tuint32_t pid = getpid() & 0x3FFFFF;\n+\tint i;\n+\n+\thandle = nl_handle_alloc_cb(cb);\n+\n+\tfor (i = 0; i < 1024; i++) {\n+\t\tif (port_bitmap[i / 32] & (1 << (i % 32)))\n+\t\t\tcontinue;\n+\t\tport_bitmap[i / 32] |= 1 << (i % 32);\n+\t\tpid += i << 22;\n+\t\tbreak;\n+\t}\n+\n+\tnl_socket_set_local_port(handle, pid);\n+\n+\treturn handle;\n+}\n+\n+static void capwap_handle_destroy(struct nl_handle *handle)\n+{\n+\tuint32_t port = nl_socket_get_local_port(handle);\n+\n+\tport >>= 22;\n+\tport_bitmap[port / 32] &= ~(1 << (port % 32));\n+\n+\tnl_handle_destroy(handle);\n+}\n+#endif /* CONFIG_LIBNL20 */\n+\n+\n+static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)\n+{\n+\tstruct nl_handle *handle;\n+\thandle = capwap_handle_alloc(cb);\n+\tif (handle == NULL) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate netlink \"\n+\t\t\t   \"callbacks (%s)\", dbg);\n+\t\treturn NULL;\n+\t}\n+\n+\tif (genl_connect(handle)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to connect to generic \"\n+\t\t\t   \"netlink (%s)\", dbg);\n+\t\tcapwap_handle_destroy(handle);\n+\t\treturn NULL;\n+\t}\n+\n+\treturn handle;\n+}\n+\n+static struct nl_cache * nl_create_cache(struct nl_handle *handle)\n+{\n+        struct nl_cache *cache;\n+\twpa_printf(MSG_ERROR, \"nl_create_cache()\");\n+        if (genl_ctrl_alloc_cache(handle, &cache) < 0) {\n+                wpa_printf(MSG_ERROR, \"capwap: Failed to allocate generic \"\n+                           \"netlink cache\");\n+                return NULL;\n+        }\n+\n+\treturn cache;\n+}\n+\n+\n+\n+static void nl_destroy_handles(struct nl_handle **handle)\n+{\n+\tif (*handle == NULL)\n+\t\treturn;\n+\tcapwap_handle_destroy(*handle);\n+\t*handle = NULL;\n+}\n+\n+static void nl_destroy_cache(struct nl_cache **cache)\n+{\n+\tif (*cache == NULL)\n+\t\treturn;\n+\tnl_cache_free(*cache);\n+\t*cache = NULL;\n+}\n+\n+\n+#ifndef IFF_LOWER_UP\n+#define IFF_LOWER_UP   0x10000         /* driver signals L1 up         */\n+#endif\n+#ifndef IFF_DORMANT\n+#define IFF_DORMANT    0x20000         /* driver signals dormant       */\n+#endif\n+\n+#ifndef IF_OPER_DORMANT\n+#define IF_OPER_DORMANT 5\n+#endif\n+#ifndef IF_OPER_UP\n+#define IF_OPER_UP 6\n+#endif\n+\n+struct capwap_global {\n+\tstruct dl_list interfaces;\n+\tint if_add_ifindex;\n+\tstruct netlink_data *netlink;\n+\tstruct nl_cb *nl_cb;\n+\tstruct nl_handle *nl;\n+\tstruct genl_family *capwap;\n+\tint ioctl_sock; /* socket for ioctl() use */\n+\tstruct nl_cache *nl_cache;\n+\tstruct nl_cache *nl_event_cache;\n+\tstruct nl_handle *nl_event;\n+};\n+\n+struct capwap_wiphy_data {\n+\tstruct dl_list list;\n+\tstruct dl_list bsss;\n+\tstruct dl_list drvs;\n+\n+\tstruct nl_handle *nl_beacons;\n+\tstruct nl_cb *nl_cb;\n+\tstruct nl_cache *nl_beacons_cache;\n+\tint wiphy_idx;\n+};\n+\n+static void capwap_global_deinit(void *priv);\n+\n+struct i802_bss {\n+\tstruct wpa_driver_capwap_data *drv;\n+\tstruct i802_bss *next;\n+\tint ifindex;\n+\tchar ifname[IFNAMSIZ + 1];\n+\tchar brname[IFNAMSIZ];\n+\tunsigned int beacon_set:1;\n+\tunsigned int added_if_into_bridge:1;\n+\tunsigned int added_bridge:1;\n+\tunsigned int in_deinit:1;\n+\tstruct nl_cache *nl_mgmt_cache;\n+\tstruct nl_cache *nl_preq_cache;\n+\tu8 addr[ETH_ALEN];\n+\n+\tint freq;\n+\n+\tvoid *ctx;\n+\tstruct nl_handle *nl_preq, *nl_mgmt;\n+\tstruct nl_cb *nl_cb;\n+\n+\tstruct capwap_wiphy_data *wiphy_data;\n+\tstruct dl_list wiphy_list;\n+};\n+\n+struct wpa_driver_capwap_data {\n+\tstruct capwap_global *global;\n+\tstruct dl_list list;\n+\tstruct dl_list wiphy_list;\n+\tu8 addr[ETH_ALEN];\n+\tchar phyname[32];\n+\tvoid *ctx;\n+\tint ifindex;\n+\tint if_removed;\n+\tint if_disabled;\n+\tint ignore_if_down_event;\n+#ifdef CONFIG_RFKILL\n+\tstruct rfkill_data *rfkill;\n+#endif\n+\tstruct wpa_driver_capa capa;\n+\tint has_capability;\n+\n+\tint operstate;\n+\n+\tint scan_complete_events;\n+\n+\tstruct nl_cb *nl_cb;\n+\n+\tu8 auth_bssid[ETH_ALEN];\n+\tu8 bssid[ETH_ALEN];\n+\tint associated;\n+\tu8 ssid[32];\n+\tsize_t ssid_len;\n+\tenum nl80211_iftype nlmode;\n+\tenum nl80211_iftype ap_scan_as_station;\n+\tunsigned int assoc_freq;\n+\n+\tint monitor_sock;\n+\tint monitor_ifidx;\n+\tint monitor_refcount;\n+\n+\tunsigned int disabled_11b_rates:1;\n+\tunsigned int pending_remain_on_chan:1;\n+\tunsigned int in_interface_list:1;\n+\tunsigned int device_ap_sme:1;\n+\tunsigned int poll_command_supported:1;\n+\tunsigned int data_tx_status:1;\n+\tunsigned int scan_for_auth:1;\n+\tunsigned int retry_auth:1;\n+\tunsigned int use_monitor:1;\n+\tunsigned int ignore_next_local_disconnect:1;\n+\n+\tu64 remain_on_chan_cookie;\n+\tu64 send_action_cookie;\n+\n+\tunsigned int last_mgmt_freq;\n+\n+\tstruct wpa_driver_scan_filter *filter_ssids;\n+\tsize_t num_filter_ssids;\n+\n+\tstruct i802_bss first_bss;\n+\n+\tint eapol_tx_sock;\n+\n+#ifdef HOSTAPD\n+\tint eapol_sock; /* socket for EAPOL frames */\n+\n+\tint default_if_indices[16];\n+\tint *if_indices;\n+\tint num_if_indices;\n+\n+\tint last_freq;\n+\tint last_freq_ht;\n+#endif /* HOSTAPD */\n+\n+\t/* From failed authentication command */\n+\tint auth_freq;\n+\tu8 auth_bssid_[ETH_ALEN];\n+\tu8 auth_ssid[32];\n+\tsize_t auth_ssid_len;\n+\tint auth_alg;\n+\tu8 *auth_ie;\n+\tsize_t auth_ie_len;\n+\tu8 auth_wep_key[4][16];\n+\tsize_t auth_wep_key_len[4];\n+\tint auth_wep_tx_keyidx;\n+\tint auth_local_state_change;\n+\tint auth_p2p;\n+};\n+\n+\n+static void wpa_driver_capwap_deinit(struct i802_bss *bss);\n+static void wpa_driver_capwap_scan_timeout(void *eloop_ctx,\n+\t\t\t\t\t    void *timeout_ctx);\n+static int wpa_driver_capwap_set_mode(struct i802_bss *bss,\n+\t\t\t\t       enum nl80211_iftype nlmode);\n+static int\n+wpa_driver_capwap_finish_drv_init(struct wpa_driver_capwap_data *drv);\n+static int wpa_driver_capwap_mlme(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t   const u8 *addr, int cmd, u16 reason_code,\n+\t\t\t\t   int local_state_change);\n+static void capwap_remove_monitor_interface(\n+\tstruct wpa_driver_capwap_data *drv);\n+static int capwap_send_frame_cmd(struct i802_bss *bss,\n+\t\t\t\t  unsigned int freq, unsigned int wait,\n+\t\t\t\t  const u8 *buf, size_t buf_len, u64 *cookie,\n+\t\t\t\t  int no_cck, int no_ack, int offchanok);\n+static int wpa_driver_capwap_probe_req_report(struct i802_bss *bss,\n+\t\t\t\t\t       int report);\n+#ifdef ANDROID\n+static int android_pno_start(struct i802_bss *bss,\n+\t\t\t     struct wpa_driver_scan_params *params);\n+static int android_pno_stop(struct i802_bss *bss);\n+#endif /* ANDROID */\n+\n+#ifdef HOSTAPD\n+static void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\n+static void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\n+static int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\n+static int wpa_driver_capwap_if_remove(struct i802_bss *bss,\n+\t\t\t\t\tenum wpa_driver_if_type type,\n+\t\t\t\t\tconst char *ifname);\n+#else /* HOSTAPD */\n+static inline void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n+{\n+}\n+\n+static inline void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n+{\n+}\n+\n+static inline int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n+{\n+\treturn 0;\n+}\n+#endif /* HOSTAPD */\n+\n+static int wpa_driver_capwap_set_freq(struct i802_bss *bss,\n+\t\t\t\t       struct hostapd_freq_params *freq);\n+static int capwap_disable_11b_rates(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t     int ifindex, int disabled);\n+\n+static int capwap_leave_ibss(struct wpa_driver_capwap_data *drv);\n+static int wpa_driver_capwap_authenticate_retry(\n+\tstruct wpa_driver_capwap_data *drv);\n+\n+\n+static int is_ap_interface(enum nl80211_iftype nlmode)\n+{\n+\treturn (nlmode == NL80211_IFTYPE_AP ||\n+\t\tnlmode == NL80211_IFTYPE_P2P_GO);\n+}\n+\n+\n+static int is_sta_interface(enum nl80211_iftype nlmode)\n+{\n+\treturn (nlmode == NL80211_IFTYPE_STATION ||\n+\t\tnlmode == NL80211_IFTYPE_P2P_CLIENT);\n+}\n+\n+\n+static int is_p2p_interface(enum nl80211_iftype nlmode)\n+{\n+\treturn (nlmode == NL80211_IFTYPE_P2P_CLIENT ||\n+\t\tnlmode == NL80211_IFTYPE_P2P_GO);\n+}\n+\n+\n+struct capwap_bss_info_arg {\n+\tstruct wpa_driver_capwap_data *drv;\n+\tstruct wpa_scan_results *res;\n+\tunsigned int assoc_freq;\n+\tu8 assoc_bssid[ETH_ALEN];\n+};\n+\n+static int bss_info_handler(struct nl_msg *msg, void *arg);\n+\n+\n+/* capwap code */\n+static int ack_handler(struct nl_msg *msg, void *arg)\n+{\n+\tint *err = arg;\n+\t*err = 0;\n+\treturn NL_STOP;\n+}\n+\n+static int finish_handler(struct nl_msg *msg, void *arg)\n+{\n+\tint *ret = arg;\n+\t*ret = 0;\n+\treturn NL_SKIP;\n+}\n+\n+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,\n+\t\t\t void *arg)\n+{\n+\tint *ret = arg;\n+\t*ret = err->error;\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int no_seq_check(struct nl_msg *msg, void *arg)\n+{\n+\treturn NL_OK;\n+}\n+\n+\n+static int send_and_recv(struct capwap_global *global,\n+\t\t\t struct nl_handle *nl_handle, struct nl_msg *msg,\n+\t\t\t int (*valid_handler)(struct nl_msg *, void *),\n+\t\t\t void *valid_data)\n+{\n+\tstruct nl_cb *cb;\n+\tint err = -ENOMEM;\n+\n+\tcb = nl_cb_clone(global->nl_cb);\n+\tif (!cb)\n+\t\tgoto out;\n+\n+\terr = nl_send_auto_complete(nl_handle, msg);\n+\tif (err < 0)\n+\t\tgoto out;\n+\n+\terr = 1;\n+\n+\tnl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);\n+\tnl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);\n+\tnl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);\n+\n+\tif (valid_handler)\n+\t\tnl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,\n+\t\t\t  valid_handler, valid_data);\n+\n+\twhile (err > 0)\n+\t\tnl_recvmsgs(nl_handle, cb);\n+ out:\n+\tnl_cb_put(cb);\n+\tnlmsg_free(msg);\n+\treturn err;\n+}\n+\n+\n+static int send_and_recv_msgs_global(struct capwap_global *global,\n+\t\t\t\t     struct nl_msg *msg,\n+\t\t\t\t     int (*valid_handler)(struct nl_msg *, void *),\n+\t\t\t\t     void *valid_data)\n+{\n+\treturn send_and_recv(global, global->nl, msg, valid_handler,\n+\t\t\t     valid_data);\n+}\n+\n+\n+static int send_and_recv_msgs(struct wpa_driver_capwap_data *drv,\n+\t\t\t      struct nl_msg *msg,\n+\t\t\t      int (*valid_handler)(struct nl_msg *, void *),\n+\t\t\t      void *valid_data)\n+{\n+\treturn send_and_recv(drv->global, drv->global->nl, msg,\n+\t\t\t     valid_handler, valid_data);\n+}\n+\n+\n+struct family_data {\n+\tconst char *group;\n+\tint id;\n+};\n+\n+\n+static int family_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct family_data *res = arg;\n+\tstruct nlattr *tb[CTRL_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *mcgrp;\n+\tint i;\n+\n+\tnla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\tif (!tb[CTRL_ATTR_MCAST_GROUPS])\n+\t\treturn NL_SKIP;\n+\n+\tnla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {\n+\t\tstruct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];\n+\t\tnla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),\n+\t\t\t  nla_len(mcgrp), NULL);\n+\t\tif (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||\n+\t\t    !tb2[CTRL_ATTR_MCAST_GRP_ID] ||\n+\t\t    os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),\n+\t\t\t       res->group,\n+\t\t\t       nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)\n+\t\t\tcontinue;\n+\t\tres->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);\n+\t\tbreak;\n+\t};\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int nl_get_multicast_id(struct capwap_global *global,\n+\t\t\t       const char *family, const char *group)\n+{\n+\tstruct nl_msg *msg;\n+\tint ret = -1;\n+\tstruct family_data res = { group, -ENOENT };\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\tgenlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, \"nlctrl\"),\n+\t\t    0, 0, CTRL_CMD_GETFAMILY, 0);\n+\tNLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);\n+\n+\tret = send_and_recv_msgs_global(global, msg, family_handler, &res);\n+\tmsg = NULL;\n+\tif (ret == 0)\n+\t\tret = res.id;\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static void * capwap_cmd(struct wpa_driver_capwap_data *drv,\n+\t\t\t  struct nl_msg *msg, int flags, uint8_t cmd)\n+{\n+\treturn NULL;\n+}\n+\n+\n+struct wiphy_idx_data {\n+\tint wiphy_idx;\n+};\n+\n+\n+static int netdev_info_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct wiphy_idx_data *info = arg;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (tb[NL80211_ATTR_WIPHY])\n+\t\tinfo->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int capwap_get_wiphy_index(struct i802_bss *bss)\n+{\n+\tstruct nl_msg *msg;\n+\tstruct wiphy_idx_data data = {\n+\t\t.wiphy_idx = -1,\n+\t};\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\n+\tif (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)\n+\t\treturn data.wiphy_idx;\n+\tmsg = NULL;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -1;\n+}\n+\n+\n+static int capwap_register_beacons(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t    struct capwap_wiphy_data *w)\n+{\n+\tstruct nl_msg *msg;\n+\tint ret = -1;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx);\n+\n+\tret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Register beacons command \"\n+\t\t\t   \"failed: ret=%d (%s)\",\n+\t\t\t   ret, strerror(-ret));\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static void capwap_recv_beacons(int sock, void *eloop_ctx, void *handle)\n+{\n+\tstruct capwap_wiphy_data *w = eloop_ctx;\n+\n+\twpa_printf(MSG_EXCESSIVE, \"capwap: Beacon event message available\");\n+\n+\tnl_recvmsgs(handle, w->nl_cb);\n+}\n+\n+\n+static int process_beacon_event(struct nl_msg *msg, void *arg)\n+{\n+\tstruct capwap_wiphy_data *w = arg;\n+\tstruct wpa_driver_capwap_data *drv;\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tunion wpa_event_data event;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (gnlh->cmd != NL80211_CMD_FRAME) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Unexpected beacon event? (%d)\",\n+\t\t\t   gnlh->cmd);\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\tif (!tb[NL80211_ATTR_FRAME])\n+\t\treturn NL_SKIP;\n+\n+\tdl_list_for_each(drv, &w->drvs, struct wpa_driver_capwap_data,\n+\t\t\t wiphy_list) {\n+\t\tos_memset(&event, 0, sizeof(event));\n+\t\tevent.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);\n+\t\tevent.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);\n+\t\twpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static struct capwap_wiphy_data *\n+capwap_get_wiphy_data_ap(struct i802_bss *bss)\n+{\n+\tstatic DEFINE_DL_LIST(capwap_wiphys);\n+\tstruct capwap_wiphy_data *w;\n+\tint wiphy_idx, found = 0;\n+\tstruct i802_bss *tmp_bss;\n+\n+\tif (bss->wiphy_data != NULL)\n+\t\treturn bss->wiphy_data;\n+\n+\twiphy_idx = capwap_get_wiphy_index(bss);\n+\n+\tdl_list_for_each(w, &capwap_wiphys, struct capwap_wiphy_data, list) {\n+\t\tif (w->wiphy_idx == wiphy_idx)\n+\t\t\tgoto add;\n+\t}\n+\n+\t/* alloc new one */\n+\tw = os_zalloc(sizeof(*w));\n+\tif (w == NULL)\n+\t\treturn NULL;\n+\tw->wiphy_idx = wiphy_idx;\n+\tdl_list_init(&w->bsss);\n+\tdl_list_init(&w->drvs);\n+\n+\tw->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);\n+\tif (!w->nl_cb) {\n+\t\tos_free(w);\n+\t\treturn NULL;\n+\t}\n+\tnl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);\n+\tnl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,\n+\t\t  w);\n+\n+\tw->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,\n+\t\t\t\t\t \"wiphy beacons\");\n+\n+        w->nl_beacons_cache = nl_create_cache(w->nl_beacons);\n+\n+\tif (w->nl_beacons == NULL) {\n+\t\tos_free(w);\n+\t\treturn NULL;\n+\t}\n+\n+\tif (capwap_register_beacons(bss->drv, w)) {\n+                nl_destroy_cache(&w->nl_beacons_cache);\n+\t\tnl_destroy_handles(&w->nl_beacons);\n+\t\tos_free(w);\n+\t\treturn NULL;\n+\t}\n+\n+\teloop_register_read_sock(nl_socket_get_fd(w->nl_beacons),\n+\t\t\t\t capwap_recv_beacons, w, w->nl_beacons);\n+\n+\tdl_list_add(&capwap_wiphys, &w->list);\n+\n+add:\n+\t/* drv entry for this bss already there? */\n+\tdl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {\n+\t\tif (tmp_bss->drv == bss->drv) {\n+\t\t\tfound = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\t/* if not add it */\n+\tif (!found)\n+\t\tdl_list_add(&w->drvs, &bss->drv->wiphy_list);\n+\n+\tdl_list_add(&w->bsss, &bss->wiphy_list);\n+\tbss->wiphy_data = w;\n+\treturn w;\n+}\n+\n+\n+static void capwap_put_wiphy_data_ap(struct i802_bss *bss)\n+{\n+\tstruct capwap_wiphy_data *w = bss->wiphy_data;\n+\tstruct i802_bss *tmp_bss;\n+\tint found = 0;\n+\n+\tif (w == NULL)\n+\t\treturn;\n+\tbss->wiphy_data = NULL;\n+\tdl_list_del(&bss->wiphy_list);\n+\n+\t/* still any for this drv present? */\n+\tdl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {\n+\t\tif (tmp_bss->drv == bss->drv) {\n+\t\t\tfound = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\t/* if not remove it */\n+\tif (!found)\n+\t\tdl_list_del(&bss->drv->wiphy_list);\n+\n+\tif (!dl_list_empty(&w->bsss))\n+\t\treturn;\n+\n+\teloop_unregister_read_sock(nl_socket_get_fd(w->nl_beacons));\n+\n+\tnl_cb_put(w->nl_cb);\n+        nl_destroy_cache(&w->nl_beacons_cache);\n+\tnl_destroy_handles(&w->nl_beacons);\n+\tdl_list_del(&w->list);\n+\tos_free(w);\n+}\n+\n+\n+static int wpa_driver_capwap_get_bssid(void *priv, u8 *bssid)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tif (!drv->associated)\n+\t\treturn -1;\n+\tos_memcpy(bssid, drv->bssid, ETH_ALEN);\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_get_ssid(void *priv, u8 *ssid)\n+{\n+\twpa_printf(MSG_DEBUG, \"wpa_driver_capwap_get_ssid\");\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tif (!drv->associated)\n+\t\treturn -1;\n+\tos_memcpy(ssid, drv->ssid, drv->ssid_len);\n+\treturn drv->ssid_len;\n+}\n+\n+\n+static void wpa_driver_capwap_event_link(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t  char *buf, size_t len, int del)\n+{\n+\tunion wpa_event_data event;\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tif (len > sizeof(event.interface_status.ifname))\n+\t\tlen = sizeof(event.interface_status.ifname) - 1;\n+\tos_memcpy(event.interface_status.ifname, buf, len);\n+\tevent.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :\n+\t\tEVENT_INTERFACE_ADDED;\n+\n+\twpa_printf(MSG_DEBUG, \"RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s\",\n+\t\t   del ? \"DEL\" : \"NEW\",\n+\t\t   event.interface_status.ifname,\n+\t\t   del ? \"removed\" : \"added\");\n+\n+\tif (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) {\n+\t\tif (del) {\n+\t\t\tif (drv->if_removed) {\n+\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: if_removed \"\n+\t\t\t\t\t   \"already set - ignore event\");\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tdrv->if_removed = 1;\n+\t\t} else {\n+\t\t\tif (if_nametoindex(drv->first_bss.ifname) == 0) {\n+\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Interface %s \"\n+\t\t\t\t\t   \"does not exist - ignore \"\n+\t\t\t\t\t   \"RTM_NEWLINK\",\n+\t\t\t\t\t   drv->first_bss.ifname);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tif (!drv->if_removed) {\n+\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: if_removed \"\n+\t\t\t\t\t   \"already cleared - ignore event\");\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tdrv->if_removed = 0;\n+\t\t}\n+\t}\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);\n+}\n+\n+\n+static int wpa_driver_capwap_own_ifname(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t u8 *buf, size_t len)\n+{\n+\tint attrlen, rta_len;\n+\tstruct rtattr *attr;\n+\n+\tattrlen = len;\n+\tattr = (struct rtattr *) buf;\n+\n+\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n+\twhile (RTA_OK(attr, attrlen)) {\n+\t\tif (attr->rta_type == IFLA_IFNAME) {\n+\t\t\tif (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname)\n+\t\t\t    == 0)\n+\t\t\t\treturn 1;\n+\t\t\telse\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tattr = RTA_NEXT(attr, attrlen);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_own_ifindex(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t  int ifindex, u8 *buf, size_t len)\n+{\n+\tif (drv->ifindex == ifindex)\n+\t\treturn 1;\n+\n+\tif (drv->if_removed && wpa_driver_capwap_own_ifname(drv, buf, len)) {\n+\t\tdrv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Update ifindex for a removed \"\n+\t\t\t   \"interface\");\n+\t\twpa_driver_capwap_finish_drv_init(drv);\n+\t\treturn 1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static struct wpa_driver_capwap_data *\n+capwap_find_drv(struct capwap_global *global, int idx, u8 *buf, size_t len)\n+{\n+\tstruct wpa_driver_capwap_data *drv;\n+\tdl_list_for_each(drv, &global->interfaces,\n+\t\t\t struct wpa_driver_capwap_data, list) {\n+\t\tif (wpa_driver_capwap_own_ifindex(drv, idx, buf, len) ||\n+\t\t    have_ifidx(drv, idx))\n+\t\t\treturn drv;\n+\t}\n+\treturn NULL;\n+}\n+\n+\n+static void wpa_driver_capwap_event_rtm_newlink(void *ctx,\n+\t\t\t\t\t\t struct ifinfomsg *ifi,\n+\t\t\t\t\t\t u8 *buf, size_t len)\n+{\n+\tstruct capwap_global *global = ctx;\n+\tstruct wpa_driver_capwap_data *drv;\n+\tint attrlen, rta_len;\n+\tstruct rtattr *attr;\n+\tu32 brid = 0;\n+\tchar namebuf[IFNAMSIZ];\n+\n+\tdrv = capwap_find_drv(global, ifi->ifi_index, buf, len);\n+\tif (!drv) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore event for foreign \"\n+\t\t\t   \"ifindex %d\", ifi->ifi_index);\n+\t\treturn;\n+\t}\n+\n+\tif (ifi->ifi_family == AF_BRIDGE &&\n+\t    drv->nlmode != NL80211_IFTYPE_AP)\n+\t\treturn;\n+\n+\twpa_printf(MSG_DEBUG, \"RTM_NEWLINK: operstate=%d ifi_flags=0x%x \"\n+\t\t   \"(%s%s%s%s)\",\n+\t\t   drv->operstate, ifi->ifi_flags,\n+\t\t   (ifi->ifi_flags & IFF_UP) ? \"[UP]\" : \"\",\n+\t\t   (ifi->ifi_flags & IFF_RUNNING) ? \"[RUNNING]\" : \"\",\n+\t\t   (ifi->ifi_flags & IFF_LOWER_UP) ? \"[LOWER_UP]\" : \"\",\n+\t\t   (ifi->ifi_flags & IFF_DORMANT) ? \"[DORMANT]\" : \"\");\n+\n+\tif (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {\n+\t\tif (if_indextoname(ifi->ifi_index, namebuf) &&\n+\t\t    linux_iface_fake_up(drv->global->ioctl_sock,\n+\t\t\t\t   drv->first_bss.ifname) > 0) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface down \"\n+\t\t\t\t   \"event since interface %s is up\", namebuf);\n+\t\t\treturn;\n+\t\t}\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Interface down\");\n+\t\tif (drv->ignore_if_down_event) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface down \"\n+\t\t\t\t   \"event generated by mode change\");\n+\t\t\tdrv->ignore_if_down_event = 0;\n+\t\t} else {\n+\t\t\tdrv->if_disabled = 1;\n+\t\t\twpa_supplicant_event(drv->ctx,\n+\t\t\t\t\t     EVENT_INTERFACE_DISABLED, NULL);\n+\t\t}\n+\t}\n+\n+\tif (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {\n+\t\tif (if_indextoname(ifi->ifi_index, namebuf) &&\n+\t\t    linux_iface_fake_up(drv->global->ioctl_sock,\n+\t\t\t\t   drv->first_bss.ifname) == 0) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n+\t\t\t\t   \"event since interface %s is down\",\n+\t\t\t\t   namebuf);\n+\t\t} else if (if_nametoindex(drv->first_bss.ifname) == 0) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n+\t\t\t\t   \"event since interface %s does not exist\",\n+\t\t\t\t   drv->first_bss.ifname);\n+\t\t} else if (drv->if_removed) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n+\t\t\t\t   \"event since interface %s is marked \"\n+\t\t\t\t   \"removed\", drv->first_bss.ifname);\n+\t\t} else {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Interface up\");\n+\t\t\tdrv->if_disabled = 0;\n+\t\t\twpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,\n+\t\t\t\t\t     NULL);\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Some drivers send the association event before the operup event--in\n+\t * this case, lifting operstate in wpa_driver_capwap_set_operstate()\n+\t * fails. This will hit us when wpa_supplicant does not need to do\n+\t * IEEE 802.1X authentication\n+\t */\n+\tif (drv->operstate == 1 &&\n+\t    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&\n+\t    !(ifi->ifi_flags & IFF_RUNNING))\n+\t\tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,\n+\t\t\t\t       -1, IF_OPER_UP);\n+\n+\tattrlen = len;\n+\tattr = (struct rtattr *) buf;\n+\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n+\twhile (RTA_OK(attr, attrlen)) {\n+\t\tif (attr->rta_type == IFLA_IFNAME) {\n+\t\t\twpa_driver_capwap_event_link(\n+\t\t\t\tdrv,\n+\t\t\t\t((char *) attr) + rta_len,\n+\t\t\t\tattr->rta_len - rta_len, 0);\n+\t\t} else if (attr->rta_type == IFLA_MASTER)\n+\t\t\tbrid = nla_get_u32((struct nlattr *) attr);\n+\t\tattr = RTA_NEXT(attr, attrlen);\n+\t}\n+\n+\tif (ifi->ifi_family == AF_BRIDGE && brid) {\n+\t\t/* device has been added to bridge */\n+\t\tif_indextoname(brid, namebuf);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Add ifindex %u for bridge %s\",\n+\t\t\t   brid, namebuf);\n+\t\tadd_ifidx(drv, brid);\n+\t}\n+}\n+\n+\n+static void wpa_driver_capwap_event_rtm_dellink(void *ctx,\n+\t\t\t\t\t\t struct ifinfomsg *ifi,\n+\t\t\t\t\t\t u8 *buf, size_t len)\n+{\n+\tstruct capwap_global *global = ctx;\n+\tstruct wpa_driver_capwap_data *drv;\n+\tint attrlen, rta_len;\n+\tstruct rtattr *attr;\n+\tu32 brid = 0;\n+\n+\tdrv = capwap_find_drv(global, ifi->ifi_index, buf, len);\n+\tif (!drv) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore dellink event for \"\n+\t\t\t   \"foreign ifindex %d\", ifi->ifi_index);\n+\t\treturn;\n+\t}\n+\n+\tattrlen = len;\n+\tattr = (struct rtattr *) buf;\n+\n+\tif (ifi->ifi_family == AF_BRIDGE &&\n+\t    drv->nlmode != NL80211_IFTYPE_AP)\n+\t\treturn;\n+\n+\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n+\twhile (RTA_OK(attr, attrlen)) {\n+\t\tif (attr->rta_type == IFLA_IFNAME) {\n+\t\t\twpa_driver_capwap_event_link(\n+\t\t\t\tdrv,\n+\t\t\t\t((char *) attr) + rta_len,\n+\t\t\t\tattr->rta_len - rta_len, 1);\n+\t\t} else if (attr->rta_type == IFLA_MASTER)\n+\t\t\tbrid = nla_get_u32((struct nlattr *) attr);\n+\t\tattr = RTA_NEXT(attr, attrlen);\n+\t}\n+\n+\tif (ifi->ifi_family == AF_BRIDGE && brid) {\n+\t\t/* device has been removed from bridge */\n+\t\tchar namebuf[IFNAMSIZ];\n+\t\tif_indextoname(brid, namebuf);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Remove ifindex %u for bridge \"\n+\t\t\t   \"%s\", brid, namebuf);\n+\t\tdel_ifidx(drv, brid);\n+\t}\n+}\n+\n+\n+static void mlme_event_auth(struct wpa_driver_capwap_data *drv,\n+\t\t\t    const u8 *frame, size_t len)\n+{\n+\tconst struct ieee80211_mgmt *mgmt;\n+\tunion wpa_event_data event;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Authenticate event\");\n+\tmgmt = (const struct ieee80211_mgmt *) frame;\n+\tif (len < 24 + sizeof(mgmt->u.auth)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Too short association event \"\n+\t\t\t   \"frame\");\n+\t\treturn;\n+\t}\n+\n+\tos_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);\n+\tos_memset(&event, 0, sizeof(event));\n+\tos_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);\n+\tevent.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);\n+\tevent.auth.auth_transaction =\n+\t\tle_to_host16(mgmt->u.auth.auth_transaction);\n+\tevent.auth.status_code = le_to_host16(mgmt->u.auth.status_code);\n+\tif (len > 24 + sizeof(mgmt->u.auth)) {\n+\t\tevent.auth.ies = mgmt->u.auth.variable;\n+\t\tevent.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);\n+\t}\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);\n+}\n+\n+\n+static unsigned int capwap_get_assoc_freq(struct wpa_driver_capwap_data *drv)\n+{\n+\tstruct nl_msg *msg;\n+\tint ret;\n+\tstruct capwap_bss_info_arg arg;\n+\n+\tos_memset(&arg, 0, sizeof(arg));\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\tgoto nla_put_failure;\n+\n+\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\n+\targ.drv = drv;\n+\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n+\tmsg = NULL;\n+\tif (ret == 0) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Operating frequency for the \"\n+\t\t\t   \"associated BSS from scan results: %u MHz\",\n+\t\t\t   arg.assoc_freq);\n+\t\treturn arg.assoc_freq ? arg.assoc_freq : drv->assoc_freq;\n+\t}\n+\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n+\t\t   \"(%s)\", ret, strerror(-ret));\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn drv->assoc_freq;\n+}\n+\n+\n+static void mlme_event_assoc(struct wpa_driver_capwap_data *drv,\n+\t\t\t    const u8 *frame, size_t len)\n+{\n+\tconst struct ieee80211_mgmt *mgmt;\n+\tunion wpa_event_data event;\n+\tu16 status;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Associate event\");\n+\tmgmt = (const struct ieee80211_mgmt *) frame;\n+\tif (len < 24 + sizeof(mgmt->u.assoc_resp)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Too short association event \"\n+\t\t\t   \"frame\");\n+\t\treturn;\n+\t}\n+\n+\tstatus = le_to_host16(mgmt->u.assoc_resp.status_code);\n+\tif (status != WLAN_STATUS_SUCCESS) {\n+\t\tos_memset(&event, 0, sizeof(event));\n+\t\tevent.assoc_reject.bssid = mgmt->bssid;\n+\t\tif (len > 24 + sizeof(mgmt->u.assoc_resp)) {\n+\t\t\tevent.assoc_reject.resp_ies =\n+\t\t\t\t(u8 *) mgmt->u.assoc_resp.variable;\n+\t\t\tevent.assoc_reject.resp_ies_len =\n+\t\t\t\tlen - 24 - sizeof(mgmt->u.assoc_resp);\n+\t\t}\n+\t\tevent.assoc_reject.status_code = status;\n+\n+\t\twpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);\n+\t\treturn;\n+\t}\n+\n+\tdrv->associated = 1;\n+\tos_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tif (len > 24 + sizeof(mgmt->u.assoc_resp)) {\n+\t\tevent.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;\n+\t\tevent.assoc_info.resp_ies_len =\n+\t\t\tlen - 24 - sizeof(mgmt->u.assoc_resp);\n+\t}\n+\n+\tevent.assoc_info.freq = drv->assoc_freq;\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);\n+}\n+\n+\n+static void mlme_event_connect(struct wpa_driver_capwap_data *drv,\n+\t\t\t       enum nl80211_commands cmd, struct nlattr *status,\n+\t\t\t       struct nlattr *addr, struct nlattr *req_ie,\n+\t\t\t       struct nlattr *resp_ie)\n+{\n+\tunion wpa_event_data event;\n+\n+\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n+\t\t/*\n+\t\t * Avoid reporting two association events that would confuse\n+\t\t * the core code.\n+\t\t */\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore connect event (cmd=%d) \"\n+\t\t\t   \"when using userspace SME\", cmd);\n+\t\treturn;\n+\t}\n+\n+\tif (cmd == NL80211_CMD_CONNECT)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Connect event\");\n+\telse if (cmd == NL80211_CMD_ROAM)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Roam event\");\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tif (cmd == NL80211_CMD_CONNECT &&\n+\t    nla_get_u16(status) != WLAN_STATUS_SUCCESS) {\n+\t\tif (addr)\n+\t\t\tevent.assoc_reject.bssid = nla_data(addr);\n+\t\tif (resp_ie) {\n+\t\t\tevent.assoc_reject.resp_ies = nla_data(resp_ie);\n+\t\t\tevent.assoc_reject.resp_ies_len = nla_len(resp_ie);\n+\t\t}\n+\t\tevent.assoc_reject.status_code = nla_get_u16(status);\n+\t\twpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);\n+\t\treturn;\n+\t}\n+\n+\tdrv->associated = 1;\n+\tif (addr)\n+\t\tos_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);\n+\n+\tif (req_ie) {\n+\t\tevent.assoc_info.req_ies = nla_data(req_ie);\n+\t\tevent.assoc_info.req_ies_len = nla_len(req_ie);\n+\t}\n+\tif (resp_ie) {\n+\t\tevent.assoc_info.resp_ies = nla_data(resp_ie);\n+\t\tevent.assoc_info.resp_ies_len = nla_len(resp_ie);\n+\t}\n+\n+\tevent.assoc_info.freq = capwap_get_assoc_freq(drv);\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);\n+}\n+\n+\n+static void mlme_event_disconnect(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t  struct nlattr *reason, struct nlattr *addr,\n+\t\t\t\t  struct nlattr *by_ap)\n+{\n+\tunion wpa_event_data data;\n+\tunsigned int locally_generated = by_ap == NULL;\n+\n+\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n+\t\t/*\n+\t\t * Avoid reporting two disassociation events that could\n+\t\t * confuse the core code.\n+\t\t */\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore disconnect \"\n+\t\t\t   \"event when using userspace SME\");\n+\t\treturn;\n+\t}\n+\n+\tif (drv->ignore_next_local_disconnect) {\n+\t\tdrv->ignore_next_local_disconnect = 0;\n+\t\tif (locally_generated) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore disconnect \"\n+\t\t\t\t   \"event triggered during reassociation\");\n+\t\t\treturn;\n+\t\t}\n+\t\twpa_printf(MSG_WARNING, \"capwap: Was expecting local \"\n+\t\t\t   \"disconnect but got another disconnect \"\n+\t\t\t   \"event first\");\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Disconnect event\");\n+\tdrv->associated = 0;\n+\tos_memset(&data, 0, sizeof(data));\n+\tif (reason)\n+\t\tdata.deauth_info.reason_code = nla_get_u16(reason);\n+\tdata.deauth_info.locally_generated = by_ap == NULL;\n+\twpa_supplicant_event(drv->ctx, EVENT_DEAUTH, &data);\n+}\n+\n+\n+static void mlme_event_ch_switch(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t struct nlattr *freq, struct nlattr *type)\n+{\n+\tunion wpa_event_data data;\n+\tint ht_enabled = 1;\n+\tint chan_offset = 0;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Channel switch event\");\n+\n+\tif (!freq || !type)\n+\t\treturn;\n+\n+\tswitch (nla_get_u32(type)) {\n+\tcase NL80211_CHAN_NO_HT:\n+\t\tht_enabled = 0;\n+\t\tbreak;\n+\tcase NL80211_CHAN_HT20:\n+\t\tbreak;\n+\tcase NL80211_CHAN_HT40PLUS:\n+\t\tchan_offset = 1;\n+\t\tbreak;\n+\tcase NL80211_CHAN_HT40MINUS:\n+\t\tchan_offset = -1;\n+\t\tbreak;\n+\t}\n+\n+\tdata.ch_switch.freq = nla_get_u32(freq);\n+\tdata.ch_switch.ht_enabled = ht_enabled;\n+\tdata.ch_switch.ch_offset = chan_offset;\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_CH_SWITCH, &data);\n+}\n+\n+\n+static void mlme_timeout_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t       enum nl80211_commands cmd, struct nlattr *addr)\n+{\n+\tunion wpa_event_data event;\n+\tenum wpa_event_type ev;\n+\n+\tif (nla_len(addr) != ETH_ALEN)\n+\t\treturn;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d; timeout with \" MACSTR,\n+\t\t   cmd, MAC2STR((u8 *) nla_data(addr)));\n+\n+\tif (cmd == NL80211_CMD_AUTHENTICATE)\n+\t\tev = EVENT_AUTH_TIMED_OUT;\n+\telse if (cmd == NL80211_CMD_ASSOCIATE)\n+\t\tev = EVENT_ASSOC_TIMED_OUT;\n+\telse\n+\t\treturn;\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tos_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);\n+\twpa_supplicant_event(drv->ctx, ev, &event);\n+}\n+\n+\n+static void mlme_event_mgmt(struct wpa_driver_capwap_data *drv,\n+\t\t\t    struct nlattr *freq, struct nlattr *sig,\n+\t\t\t    const u8 *frame, size_t len)\n+{\n+\tconst struct ieee80211_mgmt *mgmt;\n+\tunion wpa_event_data event;\n+\tu16 fc, stype;\n+\tint ssi_signal = 0;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Frame event\");\n+\tmgmt = (const struct ieee80211_mgmt *) frame;\n+\tif (len < 24) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Too short action frame\");\n+\t\treturn;\n+\t}\n+\n+\tfc = le_to_host16(mgmt->frame_control);\n+\tstype = WLAN_FC_GET_STYPE(fc);\n+\n+\tif (sig)\n+\t\tssi_signal = (s32) nla_get_u32(sig);\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tif (freq) {\n+\t\tevent.rx_action.freq = nla_get_u32(freq);\n+\t\tdrv->last_mgmt_freq = event.rx_action.freq;\n+\t}\n+\tif (stype == WLAN_FC_STYPE_ACTION) {\n+\t\tevent.rx_action.da = mgmt->da;\n+\t\tevent.rx_action.sa = mgmt->sa;\n+\t\tevent.rx_action.bssid = mgmt->bssid;\n+\t\tevent.rx_action.category = mgmt->u.action.category;\n+\t\tevent.rx_action.data = &mgmt->u.action.category + 1;\n+\t\tevent.rx_action.len = frame + len - event.rx_action.data;\n+\t\twpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);\n+\t} else {\n+\t\tevent.rx_mgmt.frame = frame;\n+\t\tevent.rx_mgmt.frame_len = len;\n+\t\tevent.rx_mgmt.ssi_signal = ssi_signal;\n+\t\twpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);\n+\t}\n+}\n+\n+\n+static void mlme_event_mgmt_tx_status(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t      struct nlattr *cookie, const u8 *frame,\n+\t\t\t\t      size_t len, struct nlattr *ack)\n+{\n+\tunion wpa_event_data event;\n+\tconst struct ieee80211_hdr *hdr;\n+\tu16 fc;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Frame TX status event\");\n+\tif (!is_ap_interface(drv->nlmode)) {\n+\t\tu64 cookie_val;\n+\n+\t\tif (!cookie)\n+\t\t\treturn;\n+\n+\t\tcookie_val = nla_get_u64(cookie);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Action TX status:\"\n+\t\t\t   \" cookie=0%llx%s (ack=%d)\",\n+\t\t\t   (long long unsigned int) cookie_val,\n+\t\t\t   cookie_val == drv->send_action_cookie ?\n+\t\t\t   \" (match)\" : \" (unknown)\", ack != NULL);\n+\t\tif (cookie_val != drv->send_action_cookie)\n+\t\t\treturn;\n+\t}\n+\n+\thdr = (const struct ieee80211_hdr *) frame;\n+\tfc = le_to_host16(hdr->frame_control);\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tevent.tx_status.type = WLAN_FC_GET_TYPE(fc);\n+\tevent.tx_status.stype = WLAN_FC_GET_STYPE(fc);\n+\tevent.tx_status.dst = hdr->addr1;\n+\tevent.tx_status.data = frame;\n+\tevent.tx_status.data_len = len;\n+\tevent.tx_status.ack = ack != NULL;\n+\twpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);\n+}\n+\n+\n+static void mlme_event_deauth_disassoc(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t       enum wpa_event_type type,\n+\t\t\t\t       const u8 *frame, size_t len)\n+{\n+\tconst struct ieee80211_mgmt *mgmt;\n+\tunion wpa_event_data event;\n+\tconst u8 *bssid = NULL;\n+\tu16 reason_code = 0;\n+\n+\tif (type == EVENT_DEAUTH)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Deauthenticate event\");\n+\telse\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Disassociate event\");\n+\n+\tmgmt = (const struct ieee80211_mgmt *) frame;\n+\tif (len >= 24) {\n+\t\tbssid = mgmt->bssid;\n+\n+\t\tif (drv->associated != 0 &&\n+\t\t    os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&\n+\t\t    os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {\n+\t\t\t/*\n+\t\t\t * We have presumably received this deauth as a\n+\t\t\t * response to a clear_state_mismatch() outgoing\n+\t\t\t * deauth.  Don't let it take us offline!\n+\t\t\t */\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Deauth received \"\n+\t\t\t\t   \"from Unknown BSSID \" MACSTR \" -- ignoring\",\n+\t\t\t\t   MAC2STR(bssid));\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\tdrv->associated = 0;\n+\tos_memset(&event, 0, sizeof(event));\n+\n+\t/* Note: Same offset for Reason Code in both frame subtypes */\n+\tif (len >= 24 + sizeof(mgmt->u.deauth))\n+\t\treason_code = le_to_host16(mgmt->u.deauth.reason_code);\n+\n+\tif (type == EVENT_DISASSOC) {\n+\t\tevent.disassoc_info.locally_generated =\n+\t\t\t!os_memcmp(mgmt->sa, drv->first_bss.addr, ETH_ALEN);\n+\t\tevent.disassoc_info.addr = bssid;\n+\t\tevent.disassoc_info.reason_code = reason_code;\n+\t\tif (frame + len > mgmt->u.disassoc.variable) {\n+\t\t\tevent.disassoc_info.ie = mgmt->u.disassoc.variable;\n+\t\t\tevent.disassoc_info.ie_len = frame + len -\n+\t\t\t\tmgmt->u.disassoc.variable;\n+\t\t}\n+\t} else {\n+\t\tevent.deauth_info.locally_generated =\n+\t\t\t!os_memcmp(mgmt->sa, drv->first_bss.addr, ETH_ALEN);\n+\t\tevent.deauth_info.addr = bssid;\n+\t\tevent.deauth_info.reason_code = reason_code;\n+\t\tif (frame + len > mgmt->u.deauth.variable) {\n+\t\t\tevent.deauth_info.ie = mgmt->u.deauth.variable;\n+\t\t\tevent.deauth_info.ie_len = frame + len -\n+\t\t\t\tmgmt->u.deauth.variable;\n+\t\t}\n+\t}\n+\n+\twpa_supplicant_event(drv->ctx, type, &event);\n+}\n+\n+\n+static void mlme_event_unprot_disconnect(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t enum wpa_event_type type,\n+\t\t\t\t\t const u8 *frame, size_t len)\n+{\n+\tconst struct ieee80211_mgmt *mgmt;\n+\tunion wpa_event_data event;\n+\tu16 reason_code = 0;\n+\n+\tif (type == EVENT_UNPROT_DEAUTH)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Unprot Deauthenticate event\");\n+\telse\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Unprot Disassociate event\");\n+\n+\tif (len < 24)\n+\t\treturn;\n+\n+\tmgmt = (const struct ieee80211_mgmt *) frame;\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\t/* Note: Same offset for Reason Code in both frame subtypes */\n+\tif (len >= 24 + sizeof(mgmt->u.deauth))\n+\t\treason_code = le_to_host16(mgmt->u.deauth.reason_code);\n+\n+\tif (type == EVENT_UNPROT_DISASSOC) {\n+\t\tevent.unprot_disassoc.sa = mgmt->sa;\n+\t\tevent.unprot_disassoc.da = mgmt->da;\n+\t\tevent.unprot_disassoc.reason_code = reason_code;\n+\t} else {\n+\t\tevent.unprot_deauth.sa = mgmt->sa;\n+\t\tevent.unprot_deauth.da = mgmt->da;\n+\t\tevent.unprot_deauth.reason_code = reason_code;\n+\t}\n+\n+\twpa_supplicant_event(drv->ctx, type, &event);\n+}\n+\n+\n+static void mlme_event(struct wpa_driver_capwap_data *drv,\n+\t\t       enum nl80211_commands cmd, struct nlattr *frame,\n+\t\t       struct nlattr *addr, struct nlattr *timed_out,\n+\t\t       struct nlattr *freq, struct nlattr *ack,\n+\t\t       struct nlattr *cookie, struct nlattr *sig)\n+{\n+\tif (timed_out && addr) {\n+\t\tmlme_timeout_event(drv, cmd, addr);\n+\t\treturn;\n+\t}\n+\n+\tif (frame == NULL) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d without frame \"\n+\t\t\t   \"data\", cmd);\n+\t\treturn;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d\", cmd);\n+\twpa_hexdump(MSG_MSGDUMP, \"capwap: MLME event frame\",\n+\t\t    nla_data(frame), nla_len(frame));\n+\n+\tswitch (cmd) {\n+\tcase NL80211_CMD_AUTHENTICATE:\n+\t\tmlme_event_auth(drv, nla_data(frame), nla_len(frame));\n+\t\tbreak;\n+\tcase NL80211_CMD_ASSOCIATE:\n+\t\tmlme_event_assoc(drv, nla_data(frame), nla_len(frame));\n+\t\tbreak;\n+\tcase NL80211_CMD_DEAUTHENTICATE:\n+\t\tmlme_event_deauth_disassoc(drv, EVENT_DEAUTH,\n+\t\t\t\t\t   nla_data(frame), nla_len(frame));\n+\t\tbreak;\n+\tcase NL80211_CMD_DISASSOCIATE:\n+\t\tmlme_event_deauth_disassoc(drv, EVENT_DISASSOC,\n+\t\t\t\t\t   nla_data(frame), nla_len(frame));\n+\t\tbreak;\n+\tcase NL80211_CMD_FRAME:\n+\t\tmlme_event_mgmt(drv, freq, sig, nla_data(frame),\n+\t\t\t\tnla_len(frame));\n+\t\tbreak;\n+\tcase NL80211_CMD_FRAME_TX_STATUS:\n+\t\tmlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),\n+\t\t\t\t\t  nla_len(frame), ack);\n+\t\tbreak;\n+\tcase NL80211_CMD_UNPROT_DEAUTHENTICATE:\n+\t\tmlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,\n+\t\t\t\t\t     nla_data(frame), nla_len(frame));\n+\t\tbreak;\n+\tcase NL80211_CMD_UNPROT_DISASSOCIATE:\n+\t\tmlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,\n+\t\t\t\t\t     nla_data(frame), nla_len(frame));\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+\n+static void mlme_event_michael_mic_failure(struct i802_bss *bss,\n+\t\t\t\t\t   struct nlattr *tb[])\n+{\n+\tunion wpa_event_data data;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: MLME event Michael MIC failure\");\n+\tos_memset(&data, 0, sizeof(data));\n+\tif (tb[NL80211_ATTR_MAC]) {\n+\t\twpa_hexdump(MSG_DEBUG, \"capwap: Source MAC address\",\n+\t\t\t    nla_data(tb[NL80211_ATTR_MAC]),\n+\t\t\t    nla_len(tb[NL80211_ATTR_MAC]));\n+\t\tdata.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);\n+\t}\n+\tif (tb[NL80211_ATTR_KEY_SEQ]) {\n+\t\twpa_hexdump(MSG_DEBUG, \"capwap: TSC\",\n+\t\t\t    nla_data(tb[NL80211_ATTR_KEY_SEQ]),\n+\t\t\t    nla_len(tb[NL80211_ATTR_KEY_SEQ]));\n+\t}\n+\tif (tb[NL80211_ATTR_KEY_TYPE]) {\n+\t\tenum nl80211_key_type key_type =\n+\t\t\tnla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Key Type %d\", key_type);\n+\t\tif (key_type == NL80211_KEYTYPE_PAIRWISE)\n+\t\t\tdata.michael_mic_failure.unicast = 1;\n+\t} else\n+\t\tdata.michael_mic_failure.unicast = 1;\n+\n+\tif (tb[NL80211_ATTR_KEY_IDX]) {\n+\t\tu8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Key Id %d\", key_id);\n+\t}\n+\n+\twpa_supplicant_event(bss->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);\n+}\n+\n+\n+static void mlme_event_join_ibss(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t struct nlattr *tb[])\n+{\n+\tif (tb[NL80211_ATTR_MAC] == NULL) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: No address in IBSS joined \"\n+\t\t\t   \"event\");\n+\t\treturn;\n+\t}\n+\tos_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);\n+\tdrv->associated = 1;\n+\twpa_printf(MSG_DEBUG, \"capwap: IBSS \" MACSTR \" joined\",\n+\t\t   MAC2STR(drv->bssid));\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);\n+}\n+\n+\n+static void mlme_event_remain_on_channel(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t int cancel_event, struct nlattr *tb[])\n+{\n+\tunsigned int freq, chan_type, duration;\n+\tunion wpa_event_data data;\n+\tu64 cookie;\n+\n+\tif (tb[NL80211_ATTR_WIPHY_FREQ])\n+\t\tfreq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);\n+\telse\n+\t\tfreq = 0;\n+\n+\tif (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])\n+\t\tchan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);\n+\telse\n+\t\tchan_type = 0;\n+\n+\tif (tb[NL80211_ATTR_DURATION])\n+\t\tduration = nla_get_u32(tb[NL80211_ATTR_DURATION]);\n+\telse\n+\t\tduration = 0;\n+\n+\tif (tb[NL80211_ATTR_COOKIE])\n+\t\tcookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);\n+\telse\n+\t\tcookie = 0;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Remain-on-channel event (cancel=%d \"\n+\t\t   \"freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))\",\n+\t\t   cancel_event, freq, chan_type, duration,\n+\t\t   (long long unsigned int) cookie,\n+\t\t   cookie == drv->remain_on_chan_cookie ? \"match\" : \"unknown\");\n+\n+\tif (cookie != drv->remain_on_chan_cookie)\n+\t\treturn; /* not for us */\n+\n+\tif (cancel_event)\n+\t\tdrv->pending_remain_on_chan = 0;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tdata.remain_on_channel.freq = freq;\n+\tdata.remain_on_channel.duration = duration;\n+\twpa_supplicant_event(drv->ctx, cancel_event ?\n+\t\t\t     EVENT_CANCEL_REMAIN_ON_CHANNEL :\n+\t\t\t     EVENT_REMAIN_ON_CHANNEL, &data);\n+}\n+\n+\n+static void send_scan_event(struct wpa_driver_capwap_data *drv, int aborted,\n+\t\t\t    struct nlattr *tb[])\n+{\n+\tunion wpa_event_data event;\n+\tstruct nlattr *nl;\n+\tint rem;\n+\tstruct scan_info *info;\n+#define MAX_REPORT_FREQS 50\n+\tint freqs[MAX_REPORT_FREQS];\n+\tint num_freqs = 0;\n+\n+\tif (drv->scan_for_auth) {\n+\t\tdrv->scan_for_auth = 0;\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Scan results for missing \"\n+\t\t\t   \"cfg80211 BSS entry\");\n+\t\twpa_driver_capwap_authenticate_retry(drv);\n+\t\treturn;\n+\t}\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tinfo = &event.scan_info;\n+\tinfo->aborted = aborted;\n+\n+\tif (tb[NL80211_ATTR_SCAN_SSIDS]) {\n+\t\tnla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {\n+\t\t\tstruct wpa_driver_scan_ssid *s =\n+\t\t\t\t&info->ssids[info->num_ssids];\n+\t\t\ts->ssid = nla_data(nl);\n+\t\t\ts->ssid_len = nla_len(nl);\n+\t\t\tinfo->num_ssids++;\n+\t\t\tif (info->num_ssids == WPAS_MAX_SCAN_SSIDS)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {\n+\t\tnla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)\n+\t\t{\n+\t\t\tfreqs[num_freqs] = nla_get_u32(nl);\n+\t\t\tnum_freqs++;\n+\t\t\tif (num_freqs == MAX_REPORT_FREQS - 1)\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tinfo->freqs = freqs;\n+\t\tinfo->num_freqs = num_freqs;\n+\t}\n+\twpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);\n+}\n+\n+\n+static int get_link_signal(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];\n+\tstatic struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {\n+\t\t[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },\n+\t};\n+\tstruct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];\n+\tstatic struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {\n+\t\t[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },\n+\t\t[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },\n+\t\t[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },\n+\t\t[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },\n+\t};\n+\tstruct wpa_signal_info *sig_change = arg;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\tif (!tb[NL80211_ATTR_STA_INFO] ||\n+\t    nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,\n+\t\t\t     tb[NL80211_ATTR_STA_INFO], policy))\n+\t\treturn NL_SKIP;\n+\tif (!sinfo[NL80211_STA_INFO_SIGNAL])\n+\t\treturn NL_SKIP;\n+\n+\tsig_change->current_signal =\n+\t\t(s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);\n+\n+\tif (sinfo[NL80211_STA_INFO_TX_BITRATE]) {\n+\t\tif (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,\n+\t\t\t\t     sinfo[NL80211_STA_INFO_TX_BITRATE],\n+\t\t\t\t     rate_policy)) {\n+\t\t\tsig_change->current_txrate = 0;\n+\t\t} else {\n+\t\t\tif (rinfo[NL80211_RATE_INFO_BITRATE]) {\n+\t\t\t\tsig_change->current_txrate =\n+\t\t\t\t\tnla_get_u16(rinfo[\n+\t\t\t\t\t     NL80211_RATE_INFO_BITRATE]) * 100;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int capwap_get_link_signal(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t   struct wpa_signal_info *sig)\n+{\n+\tstruct nl_msg *msg;\n+\n+\tsig->current_signal = -9999;\n+\tsig->current_txrate = 0;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);\n+\n+\treturn send_and_recv_msgs(drv, msg, get_link_signal, sig);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int get_link_noise(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];\n+\tstatic struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {\n+\t\t[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },\n+\t\t[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },\n+\t};\n+\tstruct wpa_signal_info *sig_change = arg;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (!tb[NL80211_ATTR_SURVEY_INFO]) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: survey data missing!\");\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\tif (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,\n+\t\t\t     tb[NL80211_ATTR_SURVEY_INFO],\n+\t\t\t     survey_policy)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: failed to parse nested \"\n+\t\t\t   \"attributes!\");\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\tif (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])\n+\t\treturn NL_SKIP;\n+\n+\tif (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=\n+\t    sig_change->frequency)\n+\t\treturn NL_SKIP;\n+\n+\tif (!sinfo[NL80211_SURVEY_INFO_NOISE])\n+\t\treturn NL_SKIP;\n+\n+\tsig_change->current_noise =\n+\t\t(s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int capwap_get_link_noise(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t  struct wpa_signal_info *sig_change)\n+{\n+\tstruct nl_msg *msg;\n+\n+\tsig_change->current_noise = 9999;\n+\tsig_change->frequency = drv->assoc_freq;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\n+\treturn send_and_recv_msgs(drv, msg, get_link_noise, sig_change);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];\n+\tstatic struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {\n+\t\t[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },\n+\t\t[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },\n+\t};\n+\tstruct wpa_scan_results *scan_results = arg;\n+\tstruct wpa_scan_res *scan_res;\n+\tsize_t i;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (!tb[NL80211_ATTR_SURVEY_INFO]) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Survey data missing\");\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\tif (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,\n+\t\t\t     tb[NL80211_ATTR_SURVEY_INFO],\n+\t\t\t     survey_policy)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to parse nested \"\n+\t\t\t   \"attributes\");\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\tif (!sinfo[NL80211_SURVEY_INFO_NOISE])\n+\t\treturn NL_SKIP;\n+\n+\tif (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])\n+\t\treturn NL_SKIP;\n+\n+\tfor (i = 0; i < scan_results->num; ++i) {\n+\t\tscan_res = scan_results->res[i];\n+\t\tif (!scan_res)\n+\t\t\tcontinue;\n+\t\tif ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=\n+\t\t    scan_res->freq)\n+\t\t\tcontinue;\n+\t\tif (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))\n+\t\t\tcontinue;\n+\t\tscan_res->noise = (s8)\n+\t\t\tnla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);\n+\t\tscan_res->flags &= ~WPA_SCAN_NOISE_INVALID;\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int capwap_get_noise_for_scan_results(\n+\tstruct wpa_driver_capwap_data *drv,\n+\tstruct wpa_scan_results *scan_res)\n+{\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\n+\treturn send_and_recv_msgs(drv, msg, get_noise_for_scan_results,\n+\t\t\t\t  scan_res);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static void capwap_cqm_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t      struct nlattr *tb[])\n+{\n+\tstatic struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {\n+\t\t[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },\n+\t\t[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },\n+\t\t[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },\n+\t\t[NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },\n+\t};\n+\tstruct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];\n+\tenum nl80211_cqm_rssi_threshold_event event;\n+\tunion wpa_event_data ed;\n+\tstruct wpa_signal_info sig;\n+\tint res;\n+\n+\tif (tb[NL80211_ATTR_CQM] == NULL ||\n+\t    nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],\n+\t\t\t     cqm_policy)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore invalid CQM event\");\n+\t\treturn;\n+\t}\n+\n+\tos_memset(&ed, 0, sizeof(ed));\n+\n+\tif (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {\n+\t\tif (!tb[NL80211_ATTR_MAC])\n+\t\t\treturn;\n+\t\tos_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),\n+\t\t\t  ETH_ALEN);\n+\t\twpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);\n+\t\treturn;\n+\t}\n+\n+\tif (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)\n+\t\treturn;\n+\tevent = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);\n+\n+\tif (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Connection quality monitor \"\n+\t\t\t   \"event: RSSI high\");\n+\t\ted.signal_change.above_threshold = 1;\n+\t} else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Connection quality monitor \"\n+\t\t\t   \"event: RSSI low\");\n+\t\ted.signal_change.above_threshold = 0;\n+\t} else\n+\t\treturn;\n+\n+\tres = capwap_get_link_signal(drv, &sig);\n+\tif (res == 0) {\n+\t\ted.signal_change.current_signal = sig.current_signal;\n+\t\ted.signal_change.current_txrate = sig.current_txrate;\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Signal: %d dBm  txrate: %d\",\n+\t\t\t   sig.current_signal, sig.current_txrate);\n+\t}\n+\n+\tres = capwap_get_link_noise(drv, &sig);\n+\tif (res == 0) {\n+\t\ted.signal_change.current_noise = sig.current_noise;\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Noise: %d dBm\",\n+\t\t\t   sig.current_noise);\n+\t}\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);\n+}\n+\n+\n+static void capwap_new_station_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t      struct nlattr **tb)\n+{\n+\tu8 *addr;\n+\tunion wpa_event_data data;\n+\n+\tif (tb[NL80211_ATTR_MAC] == NULL)\n+\t\treturn;\n+\taddr = nla_data(tb[NL80211_ATTR_MAC]);\n+\twpa_printf(MSG_DEBUG, \"capwap: New station \" MACSTR, MAC2STR(addr));\n+\n+\tif (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {\n+\t\tu8 *ies = NULL;\n+\t\tsize_t ies_len = 0;\n+\t\tif (tb[NL80211_ATTR_IE]) {\n+\t\t\ties = nla_data(tb[NL80211_ATTR_IE]);\n+\t\t\ties_len = nla_len(tb[NL80211_ATTR_IE]);\n+\t\t}\n+\t\twpa_hexdump(MSG_DEBUG, \"capwap: Assoc Req IEs\", ies, ies_len);\n+\t\tdrv_event_assoc(drv->ctx, addr, ies, ies_len, 0);\n+\t\treturn;\n+\t}\n+\n+\tif (drv->nlmode != NL80211_IFTYPE_ADHOC)\n+\t\treturn;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tos_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);\n+\twpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);\n+}\n+\n+\n+static void capwap_del_station_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t      struct nlattr **tb)\n+{\n+\tu8 *addr;\n+\tunion wpa_event_data data;\n+\n+\tif (tb[NL80211_ATTR_MAC] == NULL)\n+\t\treturn;\n+\taddr = nla_data(tb[NL80211_ATTR_MAC]);\n+\twpa_printf(MSG_DEBUG, \"capwap: Delete station \" MACSTR,\n+\t\t   MAC2STR(addr));\n+\n+\tif (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {\n+\t\tdrv_event_disassoc(drv->ctx, addr);\n+\t\treturn;\n+\t}\n+\n+\tif (drv->nlmode != NL80211_IFTYPE_ADHOC)\n+\t\treturn;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tos_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);\n+\twpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);\n+}\n+\n+\n+static void capwap_rekey_offload_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\tstruct nlattr **tb)\n+{\n+\tstruct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];\n+\tstatic struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {\n+\t\t[NL80211_REKEY_DATA_KEK] = {\n+\t\t\t.minlen = NL80211_KEK_LEN,\n+\t\t\t.maxlen = NL80211_KEK_LEN,\n+\t\t},\n+\t\t[NL80211_REKEY_DATA_KCK] = {\n+\t\t\t.minlen = NL80211_KCK_LEN,\n+\t\t\t.maxlen = NL80211_KCK_LEN,\n+\t\t},\n+\t\t[NL80211_REKEY_DATA_REPLAY_CTR] = {\n+\t\t\t.minlen = NL80211_REPLAY_CTR_LEN,\n+\t\t\t.maxlen = NL80211_REPLAY_CTR_LEN,\n+\t\t},\n+\t};\n+\tunion wpa_event_data data;\n+\n+\tif (!tb[NL80211_ATTR_MAC])\n+\t\treturn;\n+\tif (!tb[NL80211_ATTR_REKEY_DATA])\n+\t\treturn;\n+\tif (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,\n+\t\t\t     tb[NL80211_ATTR_REKEY_DATA], rekey_policy))\n+\t\treturn;\n+\tif (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])\n+\t\treturn;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tdata.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);\n+\twpa_printf(MSG_DEBUG, \"capwap: Rekey offload event for BSSID \" MACSTR,\n+\t\t   MAC2STR(data.driver_gtk_rekey.bssid));\n+\tdata.driver_gtk_rekey.replay_ctr =\n+\t\tnla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);\n+\twpa_hexdump(MSG_DEBUG, \"capwap: Rekey offload - Replay Counter\",\n+\t\t    data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);\n+\twpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);\n+}\n+\n+\n+static void capwap_pmksa_candidate_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t  struct nlattr **tb)\n+{\n+\tstruct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];\n+\tstatic struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {\n+\t\t[NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },\n+\t\t[NL80211_PMKSA_CANDIDATE_BSSID] = {\n+\t\t\t.minlen = ETH_ALEN,\n+\t\t\t.maxlen = ETH_ALEN,\n+\t\t},\n+\t\t[NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },\n+\t};\n+\tunion wpa_event_data data;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: PMKSA candidate event\");\n+\n+\tif (!tb[NL80211_ATTR_PMKSA_CANDIDATE])\n+\t\treturn;\n+\tif (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,\n+\t\t\t     tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))\n+\t\treturn;\n+\tif (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||\n+\t    !cand[NL80211_PMKSA_CANDIDATE_BSSID])\n+\t\treturn;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tos_memcpy(data.pmkid_candidate.bssid,\n+\t\t  nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);\n+\tdata.pmkid_candidate.index =\n+\t\tnla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);\n+\tdata.pmkid_candidate.preauth =\n+\t\tcand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;\n+\twpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);\n+}\n+\n+\n+static void capwap_client_probe_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t       struct nlattr **tb)\n+{\n+\tunion wpa_event_data data;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Probe client event\");\n+\n+\tif (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])\n+\t\treturn;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tos_memcpy(data.client_poll.addr,\n+\t\t  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);\n+}\n+\n+\n+static void capwap_tdls_oper_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t    struct nlattr **tb)\n+{\n+\tunion wpa_event_data data;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: TDLS operation event\");\n+\n+\tif (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_TDLS_OPERATION])\n+\t\treturn;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tos_memcpy(data.tdls.peer, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);\n+\tswitch (nla_get_u8(tb[NL80211_ATTR_TDLS_OPERATION])) {\n+\tcase NL80211_TDLS_SETUP:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS setup request for peer \"\n+\t\t\t   MACSTR, MAC2STR(data.tdls.peer));\n+\t\tdata.tdls.oper = TDLS_REQUEST_SETUP;\n+\t\tbreak;\n+\tcase NL80211_TDLS_TEARDOWN:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS teardown request for peer \"\n+\t\t\t   MACSTR, MAC2STR(data.tdls.peer));\n+\t\tdata.tdls.oper = TDLS_REQUEST_TEARDOWN;\n+\t\tbreak;\n+\tdefault:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Unsupported TDLS operatione \"\n+\t\t\t   \"event\");\n+\t\treturn;\n+\t}\n+\tif (tb[NL80211_ATTR_REASON_CODE]) {\n+\t\tdata.tdls.reason_code =\n+\t\t\tnla_get_u16(tb[NL80211_ATTR_REASON_CODE]);\n+\t}\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_TDLS, &data);\n+}\n+\n+\n+static void capwap_connect_failed_event(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t struct nlattr **tb)\n+{\n+\tunion wpa_event_data data;\n+\tu32 reason;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Connect failed event\");\n+\n+\tif (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_CONN_FAILED_REASON])\n+\t\treturn;\n+\n+\tos_memset(&data, 0, sizeof(data));\n+\tos_memcpy(data.connect_failed_reason.addr,\n+\t\t  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);\n+\n+\treason = nla_get_u32(tb[NL80211_ATTR_CONN_FAILED_REASON]);\n+\tswitch (reason) {\n+\tcase NL80211_CONN_FAIL_MAX_CLIENTS:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Max client reached\");\n+\t\tdata.connect_failed_reason.code = MAX_CLIENT_REACHED;\n+\t\tbreak;\n+\tcase NL80211_CONN_FAIL_BLOCKED_CLIENT:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Blocked client \" MACSTR\n+\t\t\t   \" tried to connect\",\n+\t\t\t   MAC2STR(data.connect_failed_reason.addr));\n+\t\tdata.connect_failed_reason.code = BLOCKED_CLIENT;\n+\t\tbreak;\n+\tdefault:\n+\t\twpa_printf(MSG_DEBUG, \"nl8021l: Unknown connect failed reason \"\n+\t\t\t   \"%u\", reason);\n+\t\treturn;\n+\t}\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_CONNECT_FAILED_REASON, &data);\n+}\n+\n+\n+static void capwap_spurious_frame(struct i802_bss *bss, struct nlattr **tb,\n+\t\t\t\t   int wds)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tunion wpa_event_data event;\n+\n+\tif (!tb[NL80211_ATTR_MAC])\n+\t\treturn;\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tevent.rx_from_unknown.bssid = bss->addr;\n+\tevent.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);\n+\tevent.rx_from_unknown.wds = wds;\n+\n+\twpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);\n+}\n+\n+\n+static void do_process_drv_event(struct i802_bss *bss, int cmd,\n+\t\t\t\t struct nlattr **tb)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\tif (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&\n+\t    (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||\n+\t     cmd == NL80211_CMD_SCAN_ABORTED)) {\n+\t\twpa_driver_capwap_set_mode(&drv->first_bss,\n+\t\t\t\t\t    drv->ap_scan_as_station);\n+\t\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n+\t}\n+\n+\tswitch (cmd) {\n+\tcase NL80211_CMD_TRIGGER_SCAN:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Scan trigger\");\n+\t\tbreak;\n+\tcase NL80211_CMD_START_SCHED_SCAN:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan started\");\n+\t\tbreak;\n+\tcase NL80211_CMD_SCHED_SCAN_STOPPED:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stopped\");\n+\t\twpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);\n+\t\tbreak;\n+\tcase NL80211_CMD_NEW_SCAN_RESULTS:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: New scan results available\");\n+\t\tdrv->scan_complete_events = 1;\n+\t\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv,\n+\t\t\t\t     drv->ctx);\n+\t\tsend_scan_event(drv, 0, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_SCHED_SCAN_RESULTS:\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t   \"capwap: New sched scan results available\");\n+\t\tsend_scan_event(drv, 0, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_SCAN_ABORTED:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Scan aborted\");\n+\t\t/*\n+\t\t * Need to indicate that scan results are available in order\n+\t\t * not to make wpa_supplicant stop its scanning.\n+\t\t */\n+\t\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv,\n+\t\t\t\t     drv->ctx);\n+\t\tsend_scan_event(drv, 1, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_AUTHENTICATE:\n+\tcase NL80211_CMD_ASSOCIATE:\n+\tcase NL80211_CMD_DEAUTHENTICATE:\n+\tcase NL80211_CMD_DISASSOCIATE:\n+\tcase NL80211_CMD_FRAME_TX_STATUS:\n+\tcase NL80211_CMD_UNPROT_DEAUTHENTICATE:\n+\tcase NL80211_CMD_UNPROT_DISASSOCIATE:\n+\t\tmlme_event(drv, cmd, tb[NL80211_ATTR_FRAME],\n+\t\t\t   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],\n+\t\t\t   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],\n+\t\t\t   tb[NL80211_ATTR_COOKIE],\n+\t\t\t   tb[NL80211_ATTR_RX_SIGNAL_DBM]);\n+\t\tbreak;\n+\tcase NL80211_CMD_CONNECT:\n+\tcase NL80211_CMD_ROAM:\n+\t\tmlme_event_connect(drv, cmd,\n+\t\t\t\t   tb[NL80211_ATTR_STATUS_CODE],\n+\t\t\t\t   tb[NL80211_ATTR_MAC],\n+\t\t\t\t   tb[NL80211_ATTR_REQ_IE],\n+\t\t\t\t   tb[NL80211_ATTR_RESP_IE]);\n+\t\tbreak;\n+\tcase NL80211_CMD_CH_SWITCH_NOTIFY:\n+\t\tmlme_event_ch_switch(drv, tb[NL80211_ATTR_WIPHY_FREQ],\n+\t\t\t\t     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);\n+\t\tbreak;\n+\tcase NL80211_CMD_DISCONNECT:\n+\t\tmlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],\n+\t\t\t\t      tb[NL80211_ATTR_MAC],\n+\t\t\t\t      tb[NL80211_ATTR_DISCONNECTED_BY_AP]);\n+\t\tbreak;\n+\tcase NL80211_CMD_MICHAEL_MIC_FAILURE:\n+\t\tmlme_event_michael_mic_failure(bss, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_JOIN_IBSS:\n+\t\tmlme_event_join_ibss(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_REMAIN_ON_CHANNEL:\n+\t\tmlme_event_remain_on_channel(drv, 0, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:\n+\t\tmlme_event_remain_on_channel(drv, 1, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_NOTIFY_CQM:\n+\t\tcapwap_cqm_event(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_REG_CHANGE:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Regulatory domain change\");\n+\t\twpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,\n+\t\t\t\t     NULL);\n+\t\tbreak;\n+\tcase NL80211_CMD_REG_BEACON_HINT:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Regulatory beacon hint\");\n+\t\twpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,\n+\t\t\t\t     NULL);\n+\t\tbreak;\n+\tcase NL80211_CMD_NEW_STATION:\n+\t\tcapwap_new_station_event(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_DEL_STATION:\n+\t\tcapwap_del_station_event(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_SET_REKEY_OFFLOAD:\n+\t\tcapwap_rekey_offload_event(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_PMKSA_CANDIDATE:\n+\t\tcapwap_pmksa_candidate_event(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_PROBE_CLIENT:\n+\t\tcapwap_client_probe_event(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_TDLS_OPER:\n+\t\tcapwap_tdls_oper_event(drv, tb);\n+\t\tbreak;\n+\tcase NL80211_CMD_CONN_FAILED:\n+\t\tcapwap_connect_failed_event(drv, tb);\n+\t\tbreak;\n+\tdefault:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Ignored unknown event \"\n+\t\t\t   \"(cmd=%d)\", cmd);\n+\t\tbreak;\n+\t}\n+}\n+\n+\n+static int process_drv_event(struct nl_msg *msg, void *arg)\n+{\n+\tstruct wpa_driver_capwap_data *drv = arg;\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct i802_bss *bss;\n+\tint ifidx = -1;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (tb[NL80211_ATTR_IFINDEX])\n+\t\tifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);\n+\n+\tfor (bss = &drv->first_bss; bss; bss = bss->next) {\n+\t\tif (ifidx == -1 || ifidx == bss->ifindex) {\n+\t\t\tdo_process_drv_event(bss, gnlh->cmd, tb);\n+\t\t\treturn NL_SKIP;\n+\t\t}\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Ignored event (cmd=%d) for foreign \"\n+\t\t   \"interface (ifindex %d)\", gnlh->cmd, ifidx);\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int process_global_event(struct nl_msg *msg, void *arg)\n+{\n+\tstruct capwap_global *global = arg;\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct wpa_driver_capwap_data *drv, *tmp;\n+\tint ifidx = -1;\n+\tstruct i802_bss *bss;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (tb[NL80211_ATTR_IFINDEX])\n+\t\tifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);\n+\n+\tdl_list_for_each_safe(drv, tmp, &global->interfaces,\n+\t\t\t      struct wpa_driver_capwap_data, list) {\n+\t\tfor (bss = &drv->first_bss; bss; bss = bss->next) {\n+\t\t\tif (ifidx == -1 || ifidx == bss->ifindex) {\n+\t\t\t\tdo_process_drv_event(bss, gnlh->cmd, tb);\n+\t\t\t\treturn NL_SKIP;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int process_bss_event(struct nl_msg *msg, void *arg)\n+{\n+\tstruct i802_bss *bss = arg;\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tswitch (gnlh->cmd) {\n+\tcase NL80211_CMD_FRAME:\n+\tcase NL80211_CMD_FRAME_TX_STATUS:\n+\t\tmlme_event(bss->drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],\n+\t\t\t   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],\n+\t\t\t   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],\n+\t\t\t   tb[NL80211_ATTR_COOKIE],\n+\t\t\t   tb[NL80211_ATTR_RX_SIGNAL_DBM]);\n+\t\tbreak;\n+\tcase NL80211_CMD_UNEXPECTED_FRAME:\n+\t\tcapwap_spurious_frame(bss, tb, 0);\n+\t\tbreak;\n+\tcase NL80211_CMD_UNEXPECTED_4ADDR_FRAME:\n+\t\tcapwap_spurious_frame(bss, tb, 1);\n+\t\tbreak;\n+\tdefault:\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Ignored unknown event \"\n+\t\t\t   \"(cmd=%d)\", gnlh->cmd);\n+\t\tbreak;\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static void wpa_driver_capwap_event_receive(int sock, void *eloop_ctx,\n+\t\t\t\t\t     void *handle)\n+{\n+ \twpa_printf(MSG_DEBUG, \"wpa_driver_capwap_event_receive\");\t\n+\tstruct nl_cb *cb = eloop_ctx;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Event message available\");\n+\n+\tnl_recvmsgs(handle, cb);\n+}\n+\n+\n+/**\n+ * wpa_driver_capwap_set_country - ask capwap to set the regulatory domain\n+ * @priv: driver_capwap private data\n+ * @alpha2_arg: country to which to switch to\n+ * Returns: 0 on success, -1 on failure\n+ *\n+ * This asks capwap to set the regulatory domain for given\n+ * country ISO / IEC alpha2.\n+ */\n+static int wpa_driver_capwap_set_country(void *priv, const char *alpha2_arg)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tchar alpha2[3];\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\talpha2[0] = alpha2_arg[0];\n+\talpha2[1] = alpha2_arg[1];\n+\talpha2[2] = '\\0';\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);\n+\n+\tNLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);\n+\tif (send_and_recv_msgs(drv, msg, NULL, NULL))\n+\t\treturn -EINVAL;\n+\treturn 0;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -EINVAL;\n+}\n+\n+\n+struct wiphy_info_data {\n+\tstruct wpa_driver_capa *capa;\n+\n+\tunsigned int error:1;\n+\tunsigned int device_ap_sme:1;\n+\tunsigned int poll_command_supported:1;\n+\tunsigned int data_tx_status:1;\n+\tunsigned int monitor_supported:1;\n+};\n+\n+\n+static unsigned int probe_resp_offload_support(int supp_protocols)\n+{\n+\tunsigned int prot = 0;\n+\n+\tif (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)\n+\t\tprot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;\n+\tif (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)\n+\t\tprot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;\n+\tif (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)\n+\t\tprot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;\n+\tif (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)\n+\t\tprot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;\n+\n+\treturn prot;\n+}\n+\n+\n+static int wiphy_info_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct wiphy_info_data *info = arg;\n+\tint p2p_go_supported = 0, p2p_client_supported = 0;\n+\tint p2p_concurrent = 0, p2p_multichan_concurrent = 0;\n+\tint auth_supported = 0, connect_supported = 0;\n+\tstruct wpa_driver_capa *capa = info->capa;\n+\tstatic struct nla_policy\n+\tiface_combination_policy[NUM_NL80211_IFACE_COMB] = {\n+\t\t[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },\n+\t\t[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },\n+\t\t[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },\n+\t\t[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },\n+\t},\n+\tiface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {\n+\t\t[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },\n+\t\t[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },\n+\t};\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])\n+\t\tcapa->max_scan_ssids =\n+\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);\n+\n+\tif (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])\n+\t\tcapa->max_sched_scan_ssids =\n+\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);\n+\n+\tif (tb[NL80211_ATTR_MAX_MATCH_SETS])\n+\t\tcapa->max_match_sets =\n+\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);\n+\n+\tif (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {\n+\t\tstruct nlattr *nl_mode;\n+\t\tint i;\n+\t\tnla_for_each_nested(nl_mode,\n+\t\t\t\t    tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {\n+\t\t\tswitch (nla_type(nl_mode)) {\n+\t\t\tcase NL80211_IFTYPE_AP:\n+\t\t\t\tcapa->flags |= WPA_DRIVER_FLAGS_AP;\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_IFTYPE_P2P_GO:\n+\t\t\t\tp2p_go_supported = 1;\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_IFTYPE_P2P_CLIENT:\n+\t\t\t\tp2p_client_supported = 1;\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_IFTYPE_MONITOR:\n+\t\t\t\tinfo->monitor_supported = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (tb[NL80211_ATTR_INTERFACE_COMBINATIONS]) {\n+\t\tstruct nlattr *nl_combi;\n+\t\tint rem_combi;\n+\n+\t\tnla_for_each_nested(nl_combi,\n+\t\t\t\t    tb[NL80211_ATTR_INTERFACE_COMBINATIONS],\n+\t\t\t\t    rem_combi) {\n+\t\t\tstruct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];\n+\t\t\tstruct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];\n+\t\t\tstruct nlattr *nl_limit, *nl_mode;\n+\t\t\tint err, rem_limit, rem_mode;\n+\t\t\tint combination_has_p2p = 0, combination_has_mgd = 0;\n+\n+\t\t\terr = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,\n+\t\t\t\t\t       nl_combi,\n+\t\t\t\t\t       iface_combination_policy);\n+\t\t\tif (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||\n+\t\t\t    !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||\n+\t\t\t    !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])\n+\t\t\t\tgoto broken_combination;\n+\n+\t\t\tnla_for_each_nested(nl_limit,\n+\t\t\t\t\t    tb_comb[NL80211_IFACE_COMB_LIMITS],\n+\t\t\t\t\t    rem_limit) {\n+\t\t\t\terr = nla_parse_nested(tb_limit,\n+\t\t\t\t\t\t       MAX_NL80211_IFACE_LIMIT,\n+\t\t\t\t\t\t       nl_limit,\n+\t\t\t\t\t\t       iface_limit_policy);\n+\t\t\t\tif (err ||\n+\t\t\t\t    !tb_limit[NL80211_IFACE_LIMIT_TYPES])\n+\t\t\t\t\tgoto broken_combination;\n+\n+\t\t\t\tnla_for_each_nested(\n+\t\t\t\t\tnl_mode,\n+\t\t\t\t\ttb_limit[NL80211_IFACE_LIMIT_TYPES],\n+\t\t\t\t\trem_mode) {\n+\t\t\t\t\tint ift = nla_type(nl_mode);\n+\t\t\t\t\tif (ift == NL80211_IFTYPE_P2P_GO ||\n+\t\t\t\t\t    ift == NL80211_IFTYPE_P2P_CLIENT)\n+\t\t\t\t\t\tcombination_has_p2p = 1;\n+\t\t\t\t\tif (ift == NL80211_IFTYPE_STATION)\n+\t\t\t\t\t\tcombination_has_mgd = 1;\n+\t\t\t\t}\n+\t\t\t\tif (combination_has_p2p && combination_has_mgd)\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tif (combination_has_p2p && combination_has_mgd) {\n+\t\t\t\tp2p_concurrent = 1;\n+\t\t\t\tif (nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) > 1)\n+\t\t\t\t\tp2p_multichan_concurrent = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+broken_combination:\n+\t\t\t;\n+\t\t}\n+\t}\n+\n+\tif (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {\n+\t\tstruct nlattr *nl_cmd;\n+\t\tint i;\n+\n+\t\tnla_for_each_nested(nl_cmd,\n+\t\t\t\t    tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) {\n+\t\t\tswitch (nla_get_u32(nl_cmd)) {\n+\t\t\tcase NL80211_CMD_AUTHENTICATE:\n+\t\t\t\tauth_supported = 1;\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_CMD_CONNECT:\n+\t\t\t\tconnect_supported = 1;\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_CMD_START_SCHED_SCAN:\n+\t\t\t\tcapa->sched_scan_supported = 1;\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_CMD_PROBE_CLIENT:\n+\t\t\t\tinfo->poll_command_supported = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Using driver-based \"\n+\t\t\t   \"off-channel TX\");\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;\n+\t}\n+\n+\tif (tb[NL80211_ATTR_ROAM_SUPPORT]) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Using driver-based roaming\");\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;\n+\t}\n+\n+\t/* default to 5000 since early versions of mac80211 don't set it */\n+\tcapa->max_remain_on_chan = 5000;\n+\n+\tif (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;\n+\n+\tif (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION])\n+\t\tcapa->max_remain_on_chan =\n+\t\t\tnla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);\n+\n+\tif (auth_supported)\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_SME;\n+\telse if (!connect_supported) {\n+\t\twpa_printf(MSG_INFO, \"capwap: Driver does not support \"\n+\t\t\t   \"authentication/association or connect commands\");\n+\t\tinfo->error = 1;\n+\t}\n+\n+\tif (p2p_go_supported && p2p_client_supported)\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;\n+\tif (p2p_concurrent) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Use separate P2P group \"\n+\t\t\t   \"interface (driver advertised support)\");\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;\n+\n+\t\tif (p2p_multichan_concurrent) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Enable multi-channel \"\n+\t\t\t\t   \"concurrent (driver advertised support)\");\n+\t\t\tcapa->flags |=\n+\t\t\t\tWPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;\n+\t\t}\n+\t}\n+\n+\tif (tb[NL80211_ATTR_TDLS_SUPPORT]) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS supported\");\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;\n+\n+\t\tif (tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS external setup\");\n+\t\t\tcapa->flags |=\n+\t\t\t\tWPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;\n+\t\t}\n+\t}\n+\n+\tif (tb[NL80211_ATTR_DEVICE_AP_SME])\n+\t\tinfo->device_ap_sme = 1;\n+\n+\tif (tb[NL80211_ATTR_FEATURE_FLAGS]) {\n+\t\tu32 flags = nla_get_u32(tb[NL80211_ATTR_FEATURE_FLAGS]);\n+\n+\t\tif (flags & NL80211_FEATURE_SK_TX_STATUS)\n+\t\t\tinfo->data_tx_status = 1;\n+\n+\t\tif (flags & NL80211_FEATURE_INACTIVITY_TIMER)\n+\t\t\tcapa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;\n+\n+\t\tif (flags & NL80211_FEATURE_SAE)\n+\t\t\tcapa->flags |= WPA_DRIVER_FLAGS_SAE;\n+\n+\t\tif (flags & NL80211_FEATURE_NEED_OBSS_SCAN)\n+\t\t\tcapa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;\n+\t}\n+\n+\tif (tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]) {\n+\t\tint protocols =\n+\t\t\tnla_get_u32(tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Supports Probe Response \"\n+\t\t\t   \"offload in AP mode\");\n+\t\tcapa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;\n+\t\tcapa->probe_resp_offloads =\n+\t\t\tprobe_resp_offload_support(protocols);\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int wpa_driver_capwap_get_info(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t       struct wiphy_info_data *info)\n+{\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_capa(struct wpa_driver_capwap_data *drv)\n+{\n+        wpa_printf(MSG_DEBUG, \"                                                 4.wpa_driver_capwap_capa\");\n+ \tstruct wiphy_info_data info;\n+\tif (wpa_driver_capwap_get_info(drv, &info))\n+\t\treturn -1;\n+\n+\tdrv->has_capability = 1;\n+\t/* For now, assume TKIP, CCMP, WPA, WPA2 are supported */\n+\tdrv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |\n+\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |\n+\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA2 |\n+\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;\n+\tdrv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |\n+\t\tWPA_DRIVER_CAPA_ENC_WEP104 |\n+\t\tWPA_DRIVER_CAPA_ENC_TKIP |\n+\t\tWPA_DRIVER_CAPA_ENC_CCMP;\n+\tdrv->capa.auth = WPA_DRIVER_AUTH_OPEN |\n+\t\tWPA_DRIVER_AUTH_SHARED |\n+\t\tWPA_DRIVER_AUTH_LEAP;\n+\n+\tdrv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;\n+\tdrv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;\n+\tdrv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;\n+\n+\n+\tif (!info.device_ap_sme) {\n+\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;\n+\n+\t\t/*\n+\t\t * No AP SME is currently assumed to also indicate no AP MLME\n+\t\t * in the driver/firmware.\n+\t\t */\n+\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_AP_MLME;\n+\t}\n+\n+\tdrv->device_ap_sme = info.device_ap_sme;\n+\tdrv->poll_command_supported = info.poll_command_supported;\n+\tdrv->data_tx_status = info.data_tx_status;\n+\n+\t/*\n+\t * If poll command and tx status are supported, mac80211 is new enough\n+\t * to have everything we need to not need monitor interfaces.\n+\t */\n+\tdrv->use_monitor = !info.poll_command_supported || !info.data_tx_status;\n+\n+\tif (drv->device_ap_sme && drv->use_monitor) {\n+\t\t/*\n+\t\t * Non-mac80211 drivers may not support monitor interface.\n+\t\t * Make sure we do not get stuck with incorrect capability here\n+\t\t * by explicitly testing this.\n+\t\t */\n+\t\tif (!info.monitor_supported) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Disable use_monitor \"\n+\t\t\t\t   \"with device_ap_sme since no monitor mode \"\n+\t\t\t\t   \"support detected\");\n+\t\t\tdrv->use_monitor = 0;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * If we aren't going to use monitor interfaces, but the\n+\t * driver doesn't support data TX status, we won't get TX\n+\t * status for EAPOL frames.\n+\t */\n+\tif (!drv->use_monitor && !info.data_tx_status)\n+\t\tdrv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;\n+\n+\treturn 0;\n+}\n+\n+\n+#ifdef ANDROID\n+static int android_genl_ctrl_resolve(struct nl_handle *handle,\n+\t\t\t\t     const char *name)\n+{\n+\t/*\n+\t * Android ICS has very minimal genl_ctrl_resolve() implementation, so\n+\t * need to work around that.\n+\t */\n+\tstruct nl_cache *cache = NULL;\n+\tstruct genl_family *capwap = NULL;\n+\tint id = -1;\n+\n+\tif (genl_ctrl_alloc_cache(handle, &cache) < 0) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate generic \"\n+\t\t\t   \"netlink cache\");\n+\t\tgoto fail;\n+\t}\n+\n+\tcapwap = genl_ctrl_search_by_name(cache, name);\n+\tif (capwap == NULL)\n+\t\tgoto fail;\n+\n+\tid = genl_family_get_id(capwap);\n+\n+fail:\n+\tif (capwap)\n+\t\tgenl_family_put(capwap);\n+\tif (cache)\n+\t\tnl_cache_free(cache);\n+\n+\treturn id;\n+}\n+#define genl_ctrl_resolve android_genl_ctrl_resolve\n+#endif /* ANDROID */\n+\n+\n+static int wpa_driver_capwap_init_nl_global(struct capwap_global *global)\n+{\n+        wpa_printf(MSG_DEBUG, \"                                 2.wpa_driver_capwap_init_nl_global\\n\");\n+\tint ret;\n+\tglobal->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);\n+\tif (global->nl_cb == NULL) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate netlink \"\n+\t\t\t   \"callbacks\");\n+\t\treturn -1;\n+\t}\n+\n+\tglobal->nl = nl_create_handle(global->nl_cb, \"nl\");\n+\tglobal->nl_cache = nl_create_cache(global->nl);\n+\tif (global->nl == NULL)\n+\t\tgoto err;\n+\n+\tglobal->capwap = genl_ctrl_search_by_name(global->nl_cache,  \"nl80211\");\n+\tif (global->capwap == NULL) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: 'capwap' generic netlink not \"\n+\t\t\t   \"found\");\n+\t\tgoto err;\n+\t}\n+\n+\tglobal->nl_event = nl_create_handle(global->nl_cb, \"event\");\n+        global->nl_event_cache = nl_create_cache(global->nl_event); \n+\tif (global->nl_event == NULL)\n+\t\tgoto err;\n+\n+\tret = nl_get_multicast_id(global, \"nl80211\", \"scan\");\n+\tif (ret >= 0)\n+\t\tret = nl_socket_add_membership(global->nl_event, ret);\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Could not add multicast \"\n+\t\t\t   \"membership for scan events: %d (%s)\",\n+\t\t\t   ret, strerror(-ret));\n+\t\tgoto err;\n+\t}\n+\n+\tret = nl_get_multicast_id(global, \"nl80211\", \"mlme\");\n+\tif (ret >= 0)\n+\t\tret = nl_socket_add_membership(global->nl_event, ret);\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Could not add multicast \"\n+\t\t\t   \"membership for mlme events: %d (%s)\",\n+\t\t\t   ret, strerror(-ret));\n+\t\tgoto err;\n+\t}\n+\n+\tret = nl_get_multicast_id(global, \"nl80211\", \"regulatory\");\n+\tif (ret >= 0)\n+\t\tret = nl_socket_add_membership(global->nl_event, ret);\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Could not add multicast \"\n+\t\t\t   \"membership for regulatory events: %d (%s)\",\n+\t\t\t   ret, strerror(-ret));\n+\t\t/* Continue without regulatory events */\n+\t}\n+\n+\tnl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,\n+\t\t  no_seq_check, NULL);\n+\tnl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,\n+\t\t  process_global_event, global);\n+\n+\teloop_register_read_sock(nl_socket_get_fd(global->nl_event),\n+\t\t\t\t wpa_driver_capwap_event_receive,\n+\t\t\t\t global->nl_cb, global->nl_event);\n+\n+\treturn 0;\n+\n+err:\n+        nl_destroy_cache(&global->nl_event_cache);\n+        nl_destroy_cache(&global->nl_cache);\n+\tnl_destroy_handles(&global->nl_event);\n+\tnl_destroy_handles(&global->nl);\n+\tnl_cb_put(global->nl_cb);\n+\tglobal->nl_cb = NULL;\n+\treturn -1;\n+}\n+\n+\n+static int wpa_driver_capwap_init_nl(struct wpa_driver_capwap_data *drv)\n+{\n+\treturn 0;\n+}\n+\n+#ifdef CONFIG_RFKILL\n+static void wpa_driver_capwap_rfkill_blocked(void *ctx)\n+{\n+\twpa_printf(MSG_DEBUG, \"capwap: RFKILL blocked\");\n+\t/*\n+\t * This may be for any interface; use ifdown event to disable\n+\t * interface.\n+\t */\n+}\n+\n+\n+static void wpa_driver_capwap_rfkill_unblocked(void *ctx)\n+{\n+\tstruct wpa_driver_capwap_data *drv = ctx;\n+\twpa_printf(MSG_DEBUG, \"capwap: RFKILL unblocked\");\n+\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock,\n+\t\t\t\t  drv->first_bss.ifname, 1)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Could not set interface UP \"\n+\t\t\t   \"after rfkill unblock\");\n+\t\treturn;\n+\t}\n+\t/* rtnetlink ifup handler will report interface as enabled */\n+}\n+#endif /* CONFIG_RFKILL */\n+\n+\n+static void capwap_get_phy_name(struct wpa_driver_capwap_data *drv)\n+{\n+\treturn;\n+}\n+\n+static void wpa_driver_capwap_handle_eapol_tx_status(int sock,\n+\t\t\t\t\t\t      void *eloop_ctx,\n+\t\t\t\t\t\t      void *handle)\n+{\n+\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n+\tu8 data[2048];\n+\tstruct msghdr msg;\n+\tstruct iovec entry;\n+\tu8 control[512];\n+\tstruct cmsghdr *cmsg;\n+\tint res, found_ee = 0, found_wifi = 0, acked = 0;\n+\tunion wpa_event_data event;\n+\n+\tmemset(&msg, 0, sizeof(msg));\n+\tmsg.msg_iov = &entry;\n+\tmsg.msg_iovlen = 1;\n+\tentry.iov_base = data;\n+\tentry.iov_len = sizeof(data);\n+\tmsg.msg_control = &control;\n+\tmsg.msg_controllen = sizeof(control);\n+\n+\tres = recvmsg(sock, &msg, MSG_ERRQUEUE);\n+\t/* if error or not fitting 802.3 header, return */\n+\tif (res < 14)\n+\t\treturn;\n+\n+\tfor (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))\n+\t{\n+\t\tif (cmsg->cmsg_level == SOL_SOCKET &&\n+\t\t    cmsg->cmsg_type == SCM_WIFI_STATUS) {\n+\t\t\tint *ack;\n+\n+\t\t\tfound_wifi = 1;\n+\t\t\tack = (void *)CMSG_DATA(cmsg);\n+\t\t\tacked = *ack;\n+\t\t}\n+\n+\t\tif (cmsg->cmsg_level == SOL_PACKET &&\n+\t\t    cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {\n+\t\t\tstruct sock_extended_err *err =\n+\t\t\t\t(struct sock_extended_err *)CMSG_DATA(cmsg);\n+\n+\t\t\tif (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)\n+\t\t\t\tfound_ee = 1;\n+\t\t}\n+\t}\n+\n+\tif (!found_ee || !found_wifi)\n+\t\treturn;\n+\n+\tmemset(&event, 0, sizeof(event));\n+\tevent.eapol_tx_status.dst = data;\n+\tevent.eapol_tx_status.data = data + 14;\n+\tevent.eapol_tx_status.data_len = res - 14;\n+\tevent.eapol_tx_status.ack = acked;\n+\twpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);\n+}\n+\n+\n+static int capwap_init_bss(struct i802_bss *bss)\n+{\n+\tbss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);\n+\tif (!bss->nl_cb)\n+\t\treturn -1;\n+\n+\tnl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,\n+\t\t  no_seq_check, NULL);\n+\tnl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,\n+\t\t  process_bss_event, bss);\n+\n+\treturn 0;\n+}\n+\n+\n+static void capwap_destroy_bss(struct i802_bss *bss)\n+{\n+\tnl_cb_put(bss->nl_cb);\n+\tbss->nl_cb = NULL;\n+}\n+\n+\n+/**\n+ * wpa_driver_capwap_init - Initialize capwap driver interface\n+ * @ctx: context to be used when calling wpa_supplicant functions,\n+ * e.g., wpa_supplicant_event()\n+ * @ifname: interface name, e.g., wlan0\n+ * @global_priv: private driver global data from global_init()\n+ * Returns: Pointer to private data, %NULL on failure\n+ */\n+static void * wpa_driver_capwap_init(void *ctx, const char *ifname,\n+\t\t\t\t      void *global_priv)\n+{\n+\twpa_printf(MSG_DEBUG, \"                                 1.wpa_driver_capwap_init\\n\");\n+\tstruct wpa_driver_capwap_data *drv;\n+#ifdef CONFIG_RFKILL\n+\tstruct rfkill_config *rcfg;\n+#endif\n+\tstruct i802_bss *bss;\n+\n+\tif (global_priv == NULL)\n+\t\treturn NULL;\n+\tdrv = os_zalloc(sizeof(*drv));\n+\tif (drv == NULL)\n+\t\treturn NULL;\n+\tdrv->global = global_priv;\n+\tdrv->ctx = ctx;\n+\tbss = &drv->first_bss;\n+\tbss->drv = drv;\n+\tbss->ctx = ctx;\n+\n+\tos_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));\n+\tdrv->monitor_ifidx = -1;\n+\tdrv->monitor_sock = -1;\n+\tdrv->eapol_tx_sock = -1;\n+\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n+\tdrv->nlmode = NL80211_IFTYPE_STATION;\n+\n+#ifdef HOSTAPD\n+\tdrv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);\n+\tdrv->if_indices = drv->default_if_indices;\n+#endif\n+\n+\tif (wpa_driver_capwap_init_nl(drv)) {\n+\t\tos_free(drv);\n+\t\treturn NULL;\n+\t}\n+\n+\tif (capwap_init_bss(bss))\n+\t\tgoto failed;\n+\n+\tcapwap_get_phy_name(drv);\n+\n+#ifdef CONFIG_RFKILL\n+\trcfg = os_zalloc(sizeof(*rcfg));\n+\tif (rcfg == NULL)\n+\t\tgoto failed;\n+\trcfg->ctx = drv;\n+\tos_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));\n+\trcfg->blocked_cb = wpa_driver_capwap_rfkill_blocked;\n+\trcfg->unblocked_cb = wpa_driver_capwap_rfkill_unblocked;\n+\tdrv->rfkill = rfkill_init(rcfg);\n+\tif (drv->rfkill == NULL) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: RFKILL status not available\");\n+\t\tos_free(rcfg);\n+\t}\n+#endif /* CONFIG_RFKILL */\n+\n+\tif (wpa_driver_capwap_finish_drv_init(drv))\n+\t\tgoto failed;\n+\n+\tdrv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);\n+\tif (drv->eapol_tx_sock < 0)\n+\t\tgoto failed;\n+\n+\tif (drv->data_tx_status) {\n+\t\tint enabled = 1;\n+\n+\t\tif (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,\n+\t\t\t       &enabled, sizeof(enabled)) < 0) {\n+\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t\"capwap: wifi status sockopt failed\\n\");\n+\t\t\tdrv->data_tx_status = 0;\n+\t\t\tif (!drv->use_monitor)\n+\t\t\t\tdrv->capa.flags &=\n+\t\t\t\t\t~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;\n+\t\t} else {\n+\t\t\teloop_register_read_sock(drv->eapol_tx_sock,\n+\t\t\t\twpa_driver_capwap_handle_eapol_tx_status,\n+\t\t\t\tdrv, NULL);\n+\t\t}\n+\t}\n+\n+\tif (drv->global) {\n+\t\tdl_list_add(&drv->global->interfaces, &drv->list);\n+\t\tdrv->in_interface_list = 1;\n+\t}\n+\n+\treturn bss;\n+\n+failed:\n+\twpa_driver_capwap_deinit(bss);\n+\treturn NULL;\n+}\n+\n+\n+static int capwap_register_frame(struct i802_bss *bss,\n+\t\t\t\t  struct nl_handle *nl_handle,\n+\t\t\t\t  u16 type, const u8 *match, size_t match_len)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret = -1;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Register frame type=0x%x nl_handle=%p\",\n+\t\t   type, nl_handle);\n+\twpa_hexdump(MSG_DEBUG, \"capwap: Register frame match\",\n+\t\t    match, match_len);\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\tNLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);\n+\tNLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);\n+\n+\tret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Register frame command \"\n+\t\t\t   \"failed (type=%u): ret=%d (%s)\",\n+\t\t\t   type, ret, strerror(-ret));\n+\t\twpa_hexdump(MSG_DEBUG, \"capwap: Register frame match\",\n+\t\t\t    match, match_len);\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int capwap_alloc_mgmt_handle(struct i802_bss *bss)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\tif (bss->nl_mgmt) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Mgmt reporting \"\n+\t\t\t   \"already on! (nl_mgmt=%p)\", bss->nl_mgmt);\n+\t\treturn -1;\n+\t}\n+\n+\tbss->nl_mgmt = nl_create_handle(drv->nl_cb, \"mgmt\");\n+\tbss->nl_mgmt_cache = nl_create_cache(bss->nl_mgmt);\n+\tif (bss->nl_mgmt == NULL)\n+\t\treturn -1;\n+\n+\teloop_register_read_sock(nl_socket_get_fd(bss->nl_mgmt),\n+\t\t\t\t wpa_driver_capwap_event_receive, bss->nl_cb,\n+\t\t\t\t bss->nl_mgmt);\n+\n+\treturn 0;\n+}\n+\n+\n+static int capwap_register_action_frame(struct i802_bss *bss,\n+\t\t\t\t\t const u8 *match, size_t match_len)\n+{\n+\tu16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);\n+\treturn capwap_register_frame(bss, bss->nl_mgmt,\n+\t\t\t\t      type, match, match_len);\n+}\n+\n+\n+static int capwap_mgmt_subscribe_non_ap(struct i802_bss *bss)\n+{\n+\treturn 0;\n+}\n+\n+\n+static int capwap_register_spurious_class3(struct i802_bss *bss)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret = -1;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_UNEXPECTED_FRAME);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\n+\tret = send_and_recv(drv->global, bss->nl_mgmt, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Register spurious class3 \"\n+\t\t\t   \"failed: ret=%d (%s)\",\n+\t\t\t   ret, strerror(-ret));\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int capwap_mgmt_subscribe_ap(struct i802_bss *bss)\n+{\n+\tstatic const int stypes[] = {\n+\t\tWLAN_FC_STYPE_AUTH,\n+\t\tWLAN_FC_STYPE_ASSOC_REQ,\n+\t\tWLAN_FC_STYPE_REASSOC_REQ,\n+\t\tWLAN_FC_STYPE_DISASSOC,\n+\t\tWLAN_FC_STYPE_DEAUTH,\n+\t\tWLAN_FC_STYPE_ACTION,\n+\t\tWLAN_FC_STYPE_PROBE_REQ,\n+/* Beacon doesn't work as mac80211 doesn't currently allow\n+ * it, but it wouldn't really be the right thing anyway as\n+ * it isn't per interface ... maybe just dump the scan\n+ * results periodically for OLBC?\n+ */\n+//\t\tWLAN_FC_STYPE_BEACON,\n+\t};\n+\tunsigned int i;\n+\n+\tif (capwap_alloc_mgmt_handle(bss))\n+\t\treturn -1;\n+\twpa_printf(MSG_DEBUG, \"capwap: Subscribe to mgmt frames with AP \"\n+\t\t   \"handle %p\", bss->nl_mgmt);\n+\n+\tfor (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) {\n+\t\tif (capwap_register_frame(bss, bss->nl_mgmt,\n+\t\t\t\t\t   (WLAN_FC_TYPE_MGMT << 2) |\n+\t\t\t\t\t   (stypes[i] << 4),\n+\t\t\t\t\t   NULL, 0) < 0) {\n+\t\t\tgoto out_err;\n+\t\t}\n+\t}\n+\n+\tif (capwap_register_spurious_class3(bss))\n+\t\tgoto out_err;\n+\n+\tif (capwap_get_wiphy_data_ap(bss) == NULL)\n+\t\tgoto out_err;\n+\n+\treturn 0;\n+\n+out_err:\n+\teloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));\n+\tnl_destroy_cache(&bss->nl_mgmt_cache);\n+\tnl_destroy_handles(&bss->nl_mgmt);\n+\treturn -1;\n+}\n+\n+\n+static int capwap_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)\n+{\n+\tif (capwap_alloc_mgmt_handle(bss))\n+\t\treturn -1;\n+\twpa_printf(MSG_DEBUG, \"capwap: Subscribe to mgmt frames with AP \"\n+\t\t   \"handle %p (device SME)\", bss->nl_mgmt);\n+\n+\tif (capwap_register_frame(bss, bss->nl_mgmt,\n+\t\t\t\t   (WLAN_FC_TYPE_MGMT << 2) |\n+\t\t\t\t   (WLAN_FC_STYPE_ACTION << 4),\n+\t\t\t\t   NULL, 0) < 0)\n+\t\tgoto out_err;\n+\n+\treturn 0;\n+\n+out_err:\n+\teloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));\n+        nl_destroy_cache(&bss->nl_mgmt_cache);\n+\tnl_destroy_handles(&bss->nl_mgmt);\n+\treturn -1;\n+}\n+\n+\n+static void capwap_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)\n+{\n+\tif (bss->nl_mgmt == NULL)\n+\t\treturn;\n+\twpa_printf(MSG_DEBUG, \"capwap: Unsubscribe mgmt frames handle %p \"\n+\t\t   \"(%s)\", bss->nl_mgmt, reason);\n+\teloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));\n+        nl_destroy_cache(&bss->nl_mgmt_cache);\n+\tnl_destroy_handles(&bss->nl_mgmt);\n+\n+\tcapwap_put_wiphy_data_ap(bss);\n+}\n+\n+\n+#ifdef CONFIG_RFKILL\n+static void wpa_driver_capwap_send_rfkill(void *eloop_ctx, void *timeout_ctx)\n+{\n+\twpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);\n+}\n+#endif /* CONFIG_RFKILL */\n+\n+static int\n+wpa_driver_capwap_finish_drv_init_sta(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t       int *send_rfkill_event)\n+{\n+\tstruct i802_bss *bss = &drv->first_bss;\n+\n+\t/*\n+\t * Make sure the interface starts up in station mode unless this is a\n+\t * dynamically added interface (e.g., P2P) that was already configured\n+\t * with proper iftype.\n+\t */\n+\tif (drv->ifindex != drv->global->if_add_ifindex &&\n+\t    wpa_driver_capwap_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Could not configure driver to \"\n+\t\t\t   \"use managed mode\");\n+\t\treturn -1;\n+\t}\n+\n+\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {\n+#ifdef CONFIG_RFKILL\n+\t\tif (rfkill_is_blocked(drv->rfkill)) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Could not yet enable \"\n+\t\t\t\t   \"interface '%s' due to rfkill\",\n+\t\t\t\t   bss->ifname);\n+\t\t\tdrv->if_disabled = 1;\n+\t\t\t*send_rfkill_event = 1;\n+\t\t} else\n+#endif\n+\t\t{\n+\t\t\twpa_printf(MSG_ERROR, \"capwap: Could not set \"\n+\t\t\t\t   \"interface '%s' UP\", bss->ifname);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,\n+\t\t\t       1, IF_OPER_DORMANT);\n+}\n+\n+static int\n+wpa_driver_capwap_finish_drv_init(struct wpa_driver_capwap_data *drv)\n+{\n+\twpa_printf(MSG_DEBUG, \"                                         3.wpa_driver_capwap_finish_drv_init\\n\");\n+\tstruct i802_bss *bss = &drv->first_bss;\n+\tint send_rfkill_event = 0;\n+\n+\tdrv->ifindex = if_nametoindex(bss->ifname);\n+\tdrv->first_bss.ifindex = drv->ifindex;\n+\n+\tif (drv->nlmode == NL80211_IFTYPE_STATION)\n+\t\twpa_driver_capwap_finish_drv_init_sta(drv, &send_rfkill_event);\n+\n+\n+\tif (wpa_driver_capwap_capa(drv))\n+\t\treturn -1;\n+\n+\tif (linux_get_fake_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n+\t\t\t       bss->addr))\n+\t\treturn -1;\n+\n+\tif (send_rfkill_event) {\n+#ifdef CONFIG_RFKILL\n+\t\teloop_register_timeout(0, 0, wpa_driver_capwap_send_rfkill,\n+\t\t\t\t       drv, drv->ctx);\n+#endif\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_del_bss_beacon(struct i802_bss *bss)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\n+\tbss->beacon_set = 0;\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\n+\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+static int wpa_driver_capwap_del_beacon(struct wpa_driver_capwap_data *drv)\n+{\n+\tstruct i802_bss *bss;\n+\n+\tfor (bss = &drv->first_bss; bss; bss = bss->next)\n+\t\twpa_driver_capwap_del_bss_beacon(bss);\n+\n+\treturn 0;\n+}\n+\n+static int wpa_driver_capwap_stop_ap(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_del_beacon(bss->drv);\n+}\n+\n+/**\n+ * wpa_driver_capwap_deinit - Deinitialize capwap driver interface\n+ * @bss: Pointer to private capwap data from wpa_driver_capwap_init()\n+ *\n+ * Shut down driver interface and processing of driver events. Free\n+ * private data buffer if one was allocated in wpa_driver_capwap_init().\n+ */\n+static void wpa_driver_capwap_deinit(struct i802_bss *bss)\n+{\n+\twpa_printf(MSG_DEBUG,\"wpa_driver_capwap_deinit\\n\");\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+}\n+\n+\n+/**\n+ * wpa_driver_capwap_scan_timeout - Scan timeout to report scan completion\n+ * @eloop_ctx: Driver private data\n+ * @timeout_ctx: ctx argument given to wpa_driver_capwap_init()\n+ *\n+ * This function can be used as registered timeout when starting a scan to\n+ * generate a scan completed event if the driver does not report this.\n+ */\n+static void wpa_driver_capwap_scan_timeout(void *eloop_ctx, void *timeout_ctx)\n+{\n+\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n+\tif (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {\n+\t\twpa_driver_capwap_set_mode(&drv->first_bss,\n+\t\t\t\t\t    drv->ap_scan_as_station);\n+\t\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n+\t}\n+\twpa_printf(MSG_DEBUG, \"Scan timeout - try to get results\");\n+\twpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);\n+}\n+\n+\n+static struct nl_msg *\n+capwap_scan_common(struct wpa_driver_capwap_data *drv, u8 cmd,\n+\t\t    struct wpa_driver_scan_params *params)\n+{\n+\tstruct nl_msg *msg;\n+\tint err;\n+\tsize_t i;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn NULL;\n+\n+\tcapwap_cmd(drv, msg, 0, cmd);\n+\n+\tif (nla_put_u32(msg, NL80211_ATTR_IFINDEX, drv->ifindex) < 0)\n+\t\tgoto fail;\n+\n+\tif (params->num_ssids) {\n+\t\tstruct nl_msg *ssids = nlmsg_alloc();\n+\t\tif (ssids == NULL)\n+\t\t\tgoto fail;\n+\t\tfor (i = 1; i < params->num_ssids; i++) {\n+\t\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Scan SSID\",\n+\t\t\t\t\t  params->ssids[i].ssid,\n+\t\t\t\t\t  params->ssids[i].ssid_len);\n+\t\t\tif (nla_put(ssids, i + 1, params->ssids[i].ssid_len,\n+\t\t\t\t    params->ssids[i].ssid) < 0) {\n+\t\t\t\tnlmsg_free(ssids);\n+\t\t\t\tgoto fail;\n+\t\t\t}\n+\t\t}\n+\t\terr = nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);\n+\t\tnlmsg_free(ssids);\n+\t\tif (err < 0)\n+\t\t\tgoto fail;\n+\t}\n+\n+\tif (params->extra_ies) {\n+\t\twpa_hexdump(MSG_MSGDUMP, \"capwap: Scan extra IEs\",\n+\t\t\t    params->extra_ies, params->extra_ies_len);\n+\t\tif (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,\n+\t\t\t    params->extra_ies) < 0)\n+\t\t\tgoto fail;\n+\t}\n+\n+\tif (params->freqs) {\n+\t\tstruct nl_msg *freqs = nlmsg_alloc();\n+\t\tif (freqs == NULL)\n+\t\t\tgoto fail;\n+\t\tfor (i = 0; params->freqs[i]; i++) {\n+\t\t\twpa_printf(MSG_MSGDUMP, \"capwap: Scan frequency %u \"\n+\t\t\t\t   \"MHz\", params->freqs[i]);\n+\t\t\tif (nla_put_u32(freqs, i + 1, params->freqs[i]) < 0) {\n+\t\t\t\tnlmsg_free(freqs);\n+\t\t\t\tgoto fail;\n+\t\t\t}\n+\t\t}\n+\t\terr = nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES,\n+\t\t\t\t     freqs);\n+\t\tnlmsg_free(freqs);\n+\t\tif (err < 0)\n+\t\t\tgoto fail;\n+\t}\n+\n+\tos_free(drv->filter_ssids);\n+\tdrv->filter_ssids = params->filter_ssids;\n+\tparams->filter_ssids = NULL;\n+\tdrv->num_filter_ssids = params->num_filter_ssids;\n+\n+\treturn msg;\n+\n+fail:\n+\tnlmsg_free(msg);\n+\treturn NULL;\n+}\n+\n+\n+/**\n+ * wpa_driver_capwap_scan - Request the driver to initiate scan\n+ * @bss: Pointer to private driver data from wpa_driver_capwap_init()\n+ * @params: Scan parameters\n+ * Returns: 0 on success, -1 on failure\n+ */\n+static int wpa_driver_capwap_scan(struct i802_bss *bss,\n+\t\t\t\t   struct wpa_driver_scan_params *params)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret = -1, timeout;\n+\tstruct nl_msg *msg, *rates = NULL;\n+\n+\tdrv->scan_for_auth = 0;\n+\n+\tmsg = capwap_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params);\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tif (params->p2p_probe) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: P2P probe - mask SuppRates\");\n+\n+\t\trates = nlmsg_alloc();\n+\t\tif (rates == NULL)\n+\t\t\tgoto nla_put_failure;\n+\n+\t\t/*\n+\t\t * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates\n+\t\t * by masking out everything else apart from the OFDM rates 6,\n+\t\t * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz\n+\t\t * rates are left enabled.\n+\t\t */\n+\t\tNLA_PUT(rates, NL80211_BAND_2GHZ, 8,\n+\t\t\t\"\\x0c\\x12\\x18\\x24\\x30\\x48\\x60\\x6c\");\n+\t\tif (nla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates) <\n+\t\t    0)\n+\t\t\tgoto nla_put_failure;\n+\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Scan trigger failed: ret=%d \"\n+\t\t\t   \"(%s)\", ret, strerror(-ret));\n+#ifdef HOSTAPD\n+\t\tif (is_ap_interface(drv->nlmode)) {\n+\t\t\t/*\n+\t\t\t * mac80211 does not allow scan requests in AP mode, so\n+\t\t\t * try to do this in station mode.\n+\t\t\t */\n+\t\t\tif (wpa_driver_capwap_set_mode(\n+\t\t\t\t    bss, NL80211_IFTYPE_STATION))\n+\t\t\t\tgoto nla_put_failure;\n+\n+\t\t\tif (wpa_driver_capwap_scan(bss, params)) {\n+\t\t\t\twpa_driver_capwap_set_mode(bss, drv->nlmode);\n+\t\t\t\tgoto nla_put_failure;\n+\t\t\t}\n+\n+\t\t\t/* Restore AP mode when processing scan results */\n+\t\t\tdrv->ap_scan_as_station = drv->nlmode;\n+\t\t\tret = 0;\n+\t\t} else\n+\t\t\tgoto nla_put_failure;\n+#else /* HOSTAPD */\n+\t\tgoto nla_put_failure;\n+#endif /* HOSTAPD */\n+\t}\n+\n+\t/* Not all drivers generate \"scan completed\" wireless event, so try to\n+\t * read results after a timeout. */\n+\ttimeout = 10;\n+\tif (drv->scan_complete_events) {\n+\t\t/*\n+\t\t * The driver seems to deliver events to notify when scan is\n+\t\t * complete, so use longer timeout to avoid race conditions\n+\t\t * with scanning and following association request.\n+\t\t */\n+\t\ttimeout = 30;\n+\t}\n+\twpa_printf(MSG_DEBUG, \"Scan requested (ret=%d) - scan timeout %d \"\n+\t\t   \"seconds\", ret, timeout);\n+\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv, drv->ctx);\n+\teloop_register_timeout(timeout, 0, wpa_driver_capwap_scan_timeout,\n+\t\t\t       drv, drv->ctx);\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\tnlmsg_free(rates);\n+\treturn ret;\n+}\n+\n+\n+/**\n+ * wpa_driver_capwap_sched_scan - Initiate a scheduled scan\n+ * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n+ * @params: Scan parameters\n+ * @interval: Interval between scan cycles in milliseconds\n+ * Returns: 0 on success, -1 on failure or if not supported\n+ */\n+static int wpa_driver_capwap_sched_scan(void *priv,\n+\t\t\t\t\t struct wpa_driver_scan_params *params,\n+\t\t\t\t\t u32 interval)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret = -1;\n+\tstruct nl_msg *msg;\n+\tstruct nl_msg *match_set_ssid = NULL, *match_sets = NULL;\n+\tstruct nl_msg *match_set_rssi = NULL;\n+\tsize_t i;\n+\n+#ifdef ANDROID\n+\tif (!drv->capa.sched_scan_supported)\n+\t\treturn android_pno_start(bss, params);\n+#endif /* ANDROID */\n+\n+\tmsg = capwap_scan_common(drv, NL80211_CMD_START_SCHED_SCAN, params);\n+\tif (!msg)\n+\t\tgoto nla_put_failure;\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);\n+\n+\tif ((drv->num_filter_ssids &&\n+\t    (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||\n+\t    params->filter_rssi) {\n+\t\tmatch_sets = nlmsg_alloc();\n+\t\tif (match_sets == NULL)\n+\t\t\tgoto nla_put_failure;\n+\t\t\n+\t\tfor (i = 1; i < drv->num_filter_ssids; i++) {\n+\t\t\twpa_hexdump_ascii(MSG_MSGDUMP,\n+\t\t\t\t\t  \"capwap: Sched scan filter SSID\",\n+\t\t\t\t\t  drv->filter_ssids[i].ssid,\n+\t\t\t\t\t  drv->filter_ssids[i].ssid_len);\n+\n+\t\t\tmatch_set_ssid = nlmsg_alloc();\n+\t\t\tif (match_set_ssid == NULL)\n+\t\t\t\tgoto nla_put_failure;\n+\t\t\tNLA_PUT(match_set_ssid,\n+\t\t\t\tNL80211_ATTR_SCHED_SCAN_MATCH_SSID,\n+\t\t\t\tdrv->filter_ssids[i].ssid_len,\n+\t\t\t\tdrv->filter_ssids[i].ssid);\n+\n+\t\t\tif (nla_put_nested(match_sets, i + 1, match_set_ssid) <\n+\t\t\t    0)\n+\t\t\t\tgoto nla_put_failure;\n+\t\t}\n+\n+\t\tif (params->filter_rssi) {\n+\t\t\tmatch_set_rssi = nlmsg_alloc();\n+\t\t\tif (match_set_rssi == NULL)\n+\t\t\t\tgoto nla_put_failure;\n+\t\t\tNLA_PUT_U32(match_set_rssi,\n+\t\t\t\t    NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,\n+\t\t\t\t    params->filter_rssi);\n+\t\t\twpa_printf(MSG_MSGDUMP,\n+\t\t\t\t   \"capwap: Sched scan RSSI filter %d dBm\",\n+\t\t\t\t   params->filter_rssi);\n+\t\t\tif (nla_put_nested(match_sets, 0, match_set_rssi) < 0)\n+\t\t\t\tgoto nla_put_failure;\n+\t\t}\n+\n+\t\tif (nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,\n+\t\t\t\t   match_sets) < 0)\n+\t\t\tgoto nla_put_failure;\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\n+\t/* TODO: if we get an error here, we should fall back to normal scan */\n+\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan start failed: \"\n+\t\t\t   \"ret=%d (%s)\", ret, strerror(-ret));\n+\t\tgoto nla_put_failure;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Sched scan requested (ret=%d) - \"\n+\t\t   \"scan interval %d msec\", ret, interval);\n+\n+nla_put_failure:\n+\tnlmsg_free(match_set_ssid);\n+\tnlmsg_free(match_sets);\n+\tnlmsg_free(match_set_rssi);\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+/**\n+ * wpa_driver_capwap_stop_sched_scan - Stop a scheduled scan\n+ * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n+ * Returns: 0 on success, -1 on failure or if not supported\n+ */\n+static int wpa_driver_capwap_stop_sched_scan(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret = 0;\n+\tstruct nl_msg *msg;\n+\n+#ifdef ANDROID\n+\tif (!drv->capa.sched_scan_supported)\n+\t\treturn android_pno_stop(bss);\n+#endif /* ANDROID */\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stop failed: \"\n+\t\t\t   \"ret=%d (%s)\", ret, strerror(-ret));\n+\t\tgoto nla_put_failure;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stop sent (ret=%d)\", ret);\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static const u8 * capwap_get_ie(const u8 *ies, size_t ies_len, u8 ie)\n+{\n+\tconst u8 *end, *pos;\n+\n+\tif (ies == NULL)\n+\t\treturn NULL;\n+\n+\tpos = ies;\n+\tend = ies + ies_len;\n+\n+\twhile (pos + 1 < end) {\n+\t\tif (pos + 2 + pos[1] > end)\n+\t\t\tbreak;\n+\t\tif (pos[0] == ie)\n+\t\t\treturn pos;\n+\t\tpos += 2 + pos[1];\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+\n+static int capwap_scan_filtered(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t const u8 *ie, size_t ie_len)\n+{\n+\tconst u8 *ssid;\n+\tsize_t i;\n+\n+\tif (drv->filter_ssids == NULL)\n+\t\treturn 0;\n+\n+\tssid = capwap_get_ie(ie, ie_len, WLAN_EID_SSID);\n+\tif (ssid == NULL)\n+\t\treturn 1;\n+\n+\tfor (i = 0; i < drv->num_filter_ssids; i++) {\n+\t\tif (ssid[1] == drv->filter_ssids[i].ssid_len &&\n+\t\t    os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==\n+\t\t    0)\n+\t\t\treturn 0;\n+\t}\n+\n+\treturn 1;\n+}\n+\n+\n+static int bss_info_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *bss[NL80211_BSS_MAX + 1];\n+\tstatic struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {\n+\t\t[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },\n+\t\t[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },\n+\t\t[NL80211_BSS_TSF] = { .type = NLA_U64 },\n+\t\t[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },\n+\t\t[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },\n+\t\t[NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },\n+\t\t[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },\n+\t\t[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },\n+\t\t[NL80211_BSS_STATUS] = { .type = NLA_U32 },\n+\t\t[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },\n+\t\t[NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },\n+\t};\n+\tstruct capwap_bss_info_arg *_arg = arg;\n+\tstruct wpa_scan_results *res = _arg->res;\n+\tstruct wpa_scan_res **tmp;\n+\tstruct wpa_scan_res *r;\n+\tconst u8 *ie, *beacon_ie;\n+\tsize_t ie_len, beacon_ie_len;\n+\tu8 *pos;\n+\tsize_t i;\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\tif (!tb[NL80211_ATTR_BSS])\n+\t\treturn NL_SKIP;\n+\tif (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],\n+\t\t\t     bss_policy))\n+\t\treturn NL_SKIP;\n+\tif (bss[NL80211_BSS_STATUS]) {\n+\t\tenum nl80211_bss_status status;\n+\t\tstatus = nla_get_u32(bss[NL80211_BSS_STATUS]);\n+\t\tif (status == NL80211_BSS_STATUS_ASSOCIATED &&\n+\t\t    bss[NL80211_BSS_FREQUENCY]) {\n+\t\t\t_arg->assoc_freq =\n+\t\t\t\tnla_get_u32(bss[NL80211_BSS_FREQUENCY]);\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Associated on %u MHz\",\n+\t\t\t\t   _arg->assoc_freq);\n+\t\t}\n+\t\tif (status == NL80211_BSS_STATUS_ASSOCIATED &&\n+\t\t    bss[NL80211_BSS_BSSID]) {\n+\t\t\tos_memcpy(_arg->assoc_bssid,\n+\t\t\t\t  nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Associated with \"\n+\t\t\t\t   MACSTR, MAC2STR(_arg->assoc_bssid));\n+\t\t}\n+\t}\n+\tif (!res)\n+\t\treturn NL_SKIP;\n+\tif (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {\n+\t\tie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);\n+\t\tie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);\n+\t} else {\n+\t\tie = NULL;\n+\t\tie_len = 0;\n+\t}\n+\tif (bss[NL80211_BSS_BEACON_IES]) {\n+\t\tbeacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);\n+\t\tbeacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);\n+\t} else {\n+\t\tbeacon_ie = NULL;\n+\t\tbeacon_ie_len = 0;\n+\t}\n+\n+\tif (capwap_scan_filtered(_arg->drv, ie ? ie : beacon_ie,\n+\t\t\t\t  ie ? ie_len : beacon_ie_len))\n+\t\treturn NL_SKIP;\n+\n+\tr = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);\n+\tif (r == NULL)\n+\t\treturn NL_SKIP;\n+\tif (bss[NL80211_BSS_BSSID])\n+\t\tos_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),\n+\t\t\t  ETH_ALEN);\n+\tif (bss[NL80211_BSS_FREQUENCY])\n+\t\tr->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);\n+\tif (bss[NL80211_BSS_BEACON_INTERVAL])\n+\t\tr->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);\n+\tif (bss[NL80211_BSS_CAPABILITY])\n+\t\tr->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);\n+\tr->flags |= WPA_SCAN_NOISE_INVALID;\n+\tif (bss[NL80211_BSS_SIGNAL_MBM]) {\n+\t\tr->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);\n+\t\tr->level /= 100; /* mBm to dBm */\n+\t\tr->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;\n+\t} else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {\n+\t\tr->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);\n+\t\tr->flags |= WPA_SCAN_QUAL_INVALID;\n+\t} else\n+\t\tr->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;\n+\tif (bss[NL80211_BSS_TSF])\n+\t\tr->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);\n+\tif (bss[NL80211_BSS_SEEN_MS_AGO])\n+\t\tr->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);\n+\tr->ie_len = ie_len;\n+\tpos = (u8 *) (r + 1);\n+\tif (ie) {\n+\t\tos_memcpy(pos, ie, ie_len);\n+\t\tpos += ie_len;\n+\t}\n+\tr->beacon_ie_len = beacon_ie_len;\n+\tif (beacon_ie)\n+\t\tos_memcpy(pos, beacon_ie, beacon_ie_len);\n+\n+\tif (bss[NL80211_BSS_STATUS]) {\n+\t\tenum nl80211_bss_status status;\n+\t\tstatus = nla_get_u32(bss[NL80211_BSS_STATUS]);\n+\t\tswitch (status) {\n+\t\tcase NL80211_BSS_STATUS_AUTHENTICATED:\n+\t\t\tr->flags |= WPA_SCAN_AUTHENTICATED;\n+\t\t\tbreak;\n+\t\tcase NL80211_BSS_STATUS_ASSOCIATED:\n+\t\t\tr->flags |= WPA_SCAN_ASSOCIATED;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * cfg80211 maintains separate BSS table entries for APs if the same\n+\t * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does\n+\t * not use frequency as a separate key in the BSS table, so filter out\n+\t * duplicated entries. Prefer associated BSS entry in such a case in\n+\t * order to get the correct frequency into the BSS table.\n+\t */\n+\tfor (i = 0; i < res->num; i++) {\n+\t\tconst u8 *s1, *s2;\n+\t\tif (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)\n+\t\t\tcontinue;\n+\n+\t\ts1 = capwap_get_ie((u8 *) (res->res[i] + 1),\n+\t\t\t\t    res->res[i]->ie_len, WLAN_EID_SSID);\n+\t\ts2 = capwap_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);\n+\t\tif (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||\n+\t\t    os_memcmp(s1, s2, 2 + s1[1]) != 0)\n+\t\t\tcontinue;\n+\n+\t\t/* Same BSSID,SSID was already included in scan results */\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Remove duplicated scan result \"\n+\t\t\t   \"for \" MACSTR, MAC2STR(r->bssid));\n+\n+\t\tif ((r->flags & WPA_SCAN_ASSOCIATED) &&\n+\t\t    !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) {\n+\t\t\tos_free(res->res[i]);\n+\t\t\tres->res[i] = r;\n+\t\t} else\n+\t\t\tos_free(r);\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\ttmp = os_realloc_array(res->res, res->num + 1,\n+\t\t\t       sizeof(struct wpa_scan_res *));\n+\tif (tmp == NULL) {\n+\t\tos_free(r);\n+\t\treturn NL_SKIP;\n+\t}\n+\ttmp[res->num++] = r;\n+\tres->res = tmp;\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static void clear_state_mismatch(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t const u8 *addr)\n+{\n+\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Clear possible state \"\n+\t\t\t   \"mismatch (\" MACSTR \")\", MAC2STR(addr));\n+\t\twpa_driver_capwap_mlme(drv, addr,\n+\t\t\t\t\tNL80211_CMD_DEAUTHENTICATE,\n+\t\t\t\t\tWLAN_REASON_PREV_AUTH_NOT_VALID, 1);\n+\t}\n+}\n+\n+\n+static void wpa_driver_capwap_check_bss_status(\n+\tstruct wpa_driver_capwap_data *drv, struct wpa_scan_results *res)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < res->num; i++) {\n+\t\tstruct wpa_scan_res *r = res->res[i];\n+\t\tif (r->flags & WPA_SCAN_AUTHENTICATED) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Scan results \"\n+\t\t\t\t   \"indicates BSS status with \" MACSTR\n+\t\t\t\t   \" as authenticated\",\n+\t\t\t\t   MAC2STR(r->bssid));\n+\t\t\tif (is_sta_interface(drv->nlmode) &&\n+\t\t\t    os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&\n+\t\t\t    os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=\n+\t\t\t    0) {\n+\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Unknown BSSID\"\n+\t\t\t\t\t   \" in local state (auth=\" MACSTR\n+\t\t\t\t\t   \" assoc=\" MACSTR \")\",\n+\t\t\t\t\t   MAC2STR(drv->auth_bssid),\n+\t\t\t\t\t   MAC2STR(drv->bssid));\n+\t\t\t\tclear_state_mismatch(drv, r->bssid);\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (r->flags & WPA_SCAN_ASSOCIATED) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Scan results \"\n+\t\t\t\t   \"indicate BSS status with \" MACSTR\n+\t\t\t\t   \" as associated\",\n+\t\t\t\t   MAC2STR(r->bssid));\n+\t\t\tif (is_sta_interface(drv->nlmode) &&\n+\t\t\t    !drv->associated) {\n+\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Local state \"\n+\t\t\t\t\t   \"(not associated) does not match \"\n+\t\t\t\t\t   \"with BSS state\");\n+\t\t\t\tclear_state_mismatch(drv, r->bssid);\n+\t\t\t} else if (is_sta_interface(drv->nlmode) &&\n+\t\t\t\t   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=\n+\t\t\t\t   0) {\n+\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Local state \"\n+\t\t\t\t\t   \"(associated with \" MACSTR \") does \"\n+\t\t\t\t\t   \"not match with BSS state\",\n+\t\t\t\t\t   MAC2STR(drv->bssid));\n+\t\t\t\tclear_state_mismatch(drv, r->bssid);\n+\t\t\t\tclear_state_mismatch(drv, drv->bssid);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+\n+static struct wpa_scan_results *\n+capwap_get_scan_results(struct wpa_driver_capwap_data *drv)\n+{\n+\tstruct nl_msg *msg;\n+\tstruct wpa_scan_results *res;\n+\tint ret;\n+\tstruct capwap_bss_info_arg arg;\n+\n+\tres = os_zalloc(sizeof(*res));\n+\tif (res == NULL)\n+\t\treturn NULL;\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\tgoto nla_put_failure;\n+\n+\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\n+\targ.drv = drv;\n+\targ.res = res;\n+\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n+\tmsg = NULL;\n+\tif (ret == 0) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Received scan results (%lu \"\n+\t\t\t   \"BSSes)\", (unsigned long) res->num);\n+\t\tcapwap_get_noise_for_scan_results(drv, res);\n+\t\treturn res;\n+\t}\n+\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n+\t\t   \"(%s)\", ret, strerror(-ret));\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\twpa_scan_results_free(res);\n+\treturn NULL;\n+}\n+\n+\n+/**\n+ * wpa_driver_capwap_get_scan_results - Fetch the latest scan results\n+ * @priv: Pointer to private wext data from wpa_driver_capwap_init()\n+ * Returns: Scan results on success, -1 on failure\n+ */\n+static struct wpa_scan_results *\n+wpa_driver_capwap_get_scan_results(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct wpa_scan_results *res;\n+\n+\tres = capwap_get_scan_results(drv);\n+\tif (res)\n+\t\twpa_driver_capwap_check_bss_status(drv, res);\n+\treturn res;\n+}\n+\n+\n+static void capwap_dump_scan(struct wpa_driver_capwap_data *drv)\n+{\n+\tstruct wpa_scan_results *res;\n+\tsize_t i;\n+\n+\tres = capwap_get_scan_results(drv);\n+\tif (res == NULL) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to get scan results\");\n+\t\treturn;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Scan result dump\");\n+\tfor (i = 0; i < res->num; i++) {\n+\t\tstruct wpa_scan_res *r = res->res[i];\n+\t\twpa_printf(MSG_DEBUG, \"capwap: %d/%d \" MACSTR \"%s%s\",\n+\t\t\t   (int) i, (int) res->num, MAC2STR(r->bssid),\n+\t\t\t   r->flags & WPA_SCAN_AUTHENTICATED ? \" [auth]\" : \"\",\n+\t\t\t   r->flags & WPA_SCAN_ASSOCIATED ? \" [assoc]\" : \"\");\n+\t}\n+\n+\twpa_scan_results_free(res);\n+}\n+\n+\n+static int wpa_driver_capwap_set_key(const char *ifname, struct i802_bss *bss,\n+\t\t\t\t      enum wpa_alg alg, const u8 *addr,\n+\t\t\t\t      int key_idx, int set_tx,\n+\t\t\t\t      const u8 *seq, size_t seq_len,\n+\t\t\t\t      const u8 *key, size_t key_len)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ifindex = if_nametoindex(ifname);\n+\tstruct nl_msg *msg;\n+\tint ret;\n+\n+\twpa_printf(MSG_DEBUG, \"%s: ifindex=%d alg=%d addr=%p key_idx=%d \"\n+\t\t   \"set_tx=%d seq_len=%lu key_len=%lu\",\n+\t\t   __func__, ifindex, alg, addr, key_idx, set_tx,\n+\t\t   (unsigned long) seq_len, (unsigned long) key_len);\n+#ifdef CONFIG_TDLS\n+\tif (key_idx == -1)\n+\t\tkey_idx = 0;\n+#endif /* CONFIG_TDLS */\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tif (alg == WPA_ALG_NONE) {\n+\t\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);\n+\t} else {\n+\t\tcapwap_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);\n+\t\tNLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);\n+\t\tswitch (alg) {\n+\t\tcase WPA_ALG_WEP:\n+\t\t\tif (key_len == 5)\n+\t\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n+\t\t\telse\n+\t\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n+\t\t\tbreak;\n+\t\tcase WPA_ALG_TKIP:\n+\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_TKIP);\n+\t\t\tbreak;\n+\t\tcase WPA_ALG_CCMP:\n+\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_CCMP);\n+\t\t\tbreak;\n+\t\tcase WPA_ALG_GCMP:\n+\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_GCMP);\n+\t\t\tbreak;\n+\t\tcase WPA_ALG_IGTK:\n+\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_AES_CMAC);\n+\t\t\tbreak;\n+\t\tcase WPA_ALG_SMS4:\n+\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_SMS4);\n+\t\t\tbreak;\n+\t\tcase WPA_ALG_KRK:\n+\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_KRK);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\twpa_printf(MSG_ERROR, \"%s: Unsupported encryption \"\n+\t\t\t\t   \"algorithm %d\", __func__, alg);\n+\t\t\tnlmsg_free(msg);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tif (seq && seq_len)\n+\t\tNLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);\n+\n+\tif (addr && !is_broadcast_ether_addr(addr)) {\n+\t\twpa_printf(MSG_DEBUG, \"   addr=\" MACSTR, MAC2STR(addr));\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\n+\t\tif (alg != WPA_ALG_WEP && key_idx && !set_tx) {\n+\t\t\twpa_printf(MSG_DEBUG, \"   RSN IBSS RX GTK\");\n+\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE,\n+\t\t\t\t    NL80211_KEYTYPE_GROUP);\n+\t\t}\n+\t} else if (addr && is_broadcast_ether_addr(addr)) {\n+\t\tstruct nl_msg *types;\n+\t\tint err;\n+\t\twpa_printf(MSG_DEBUG, \"   broadcast key\");\n+\t\ttypes = nlmsg_alloc();\n+\t\tif (!types)\n+\t\t\tgoto nla_put_failure;\n+\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);\n+\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n+\t\t\t\t     types);\n+\t\tnlmsg_free(types);\n+\t\tif (err)\n+\t\t\tgoto nla_put_failure;\n+\t}\n+\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tif ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)\n+\t\tret = 0;\n+\tif (ret)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: set_key failed; err=%d %s)\",\n+\t\t\t   ret, strerror(-ret));\n+\n+\t/*\n+\t * If we failed or don't need to set the default TX key (below),\n+\t * we're done here.\n+\t */\n+\tif (ret || !set_tx || alg == WPA_ALG_NONE)\n+\t\treturn ret;\n+\tif (is_ap_interface(drv->nlmode) && addr &&\n+\t    !is_broadcast_ether_addr(addr))\n+\t\treturn ret;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);\n+\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n+\tif (alg == WPA_ALG_IGTK)\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT);\n+\telse\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);\n+\tif (addr && is_broadcast_ether_addr(addr)) {\n+\t\tstruct nl_msg *types;\n+\t\tint err;\n+\t\ttypes = nlmsg_alloc();\n+\t\tif (!types)\n+\t\t\tgoto nla_put_failure;\n+\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);\n+\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n+\t\t\t\t     types);\n+\t\tnlmsg_free(types);\n+\t\tif (err)\n+\t\t\tgoto nla_put_failure;\n+\t} else if (addr) {\n+\t\tstruct nl_msg *types;\n+\t\tint err;\n+\t\ttypes = nlmsg_alloc();\n+\t\tif (!types)\n+\t\t\tgoto nla_put_failure;\n+\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST);\n+\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n+\t\t\t\t     types);\n+\t\tnlmsg_free(types);\n+\t\tif (err)\n+\t\t\tgoto nla_put_failure;\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tif (ret == -ENOENT)\n+\t\tret = 0;\n+\tif (ret)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: set_key default failed; \"\n+\t\t\t   \"err=%d %s)\", ret, strerror(-ret));\n+\treturn ret;\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,\n+\t\t      int key_idx, int defkey,\n+\t\t      const u8 *seq, size_t seq_len,\n+\t\t      const u8 *key, size_t key_len)\n+{\n+\tstruct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);\n+\tif (!key_attr)\n+\t\treturn -1;\n+\n+\tif (defkey && alg == WPA_ALG_IGTK)\n+\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);\n+\telse if (defkey)\n+\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);\n+\n+\tNLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);\n+\n+\tswitch (alg) {\n+\tcase WPA_ALG_WEP:\n+\t\tif (key_len == 5)\n+\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n+\t\telse\n+\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n+\t\tbreak;\n+\tcase WPA_ALG_TKIP:\n+\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP);\n+\t\tbreak;\n+\tcase WPA_ALG_CCMP:\n+\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP);\n+\t\tbreak;\n+\tcase WPA_ALG_GCMP:\n+\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_GCMP);\n+\t\tbreak;\n+\tcase WPA_ALG_IGTK:\n+\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n+\t\t\t    WLAN_CIPHER_SUITE_AES_CMAC);\n+\t\tbreak;\n+\tdefault:\n+\t\twpa_printf(MSG_ERROR, \"%s: Unsupported encryption \"\n+\t\t\t   \"algorithm %d\", __func__, alg);\n+\t\treturn -1;\n+\t}\n+\n+\tif (seq && seq_len)\n+\t\tNLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);\n+\n+\tNLA_PUT(msg, NL80211_KEY_DATA, key_len, key);\n+\n+\tnla_nest_end(msg, key_attr);\n+\n+\treturn 0;\n+ nla_put_failure:\n+\treturn -1;\n+}\n+\n+\n+static int capwap_set_conn_keys(struct wpa_driver_associate_params *params,\n+\t\t\t\t struct nl_msg *msg)\n+{\n+\tint i, privacy = 0;\n+\tstruct nlattr *nl_keys, *nl_key;\n+\n+\tfor (i = 0; i < 4; i++) {\n+\t\tif (!params->wep_key[i])\n+\t\t\tcontinue;\n+\t\tprivacy = 1;\n+\t\tbreak;\n+\t}\n+\tif (params->wps == WPS_MODE_PRIVACY)\n+\t\tprivacy = 1;\n+\tif (params->pairwise_suite &&\n+\t    params->pairwise_suite != WPA_CIPHER_NONE)\n+\t\tprivacy = 1;\n+\n+\tif (!privacy)\n+\t\treturn 0;\n+\n+\tNLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);\n+\n+\tnl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);\n+\tif (!nl_keys)\n+\t\tgoto nla_put_failure;\n+\n+\tfor (i = 0; i < 4; i++) {\n+\t\tif (!params->wep_key[i])\n+\t\t\tcontinue;\n+\n+\t\tnl_key = nla_nest_start(msg, i);\n+\t\tif (!nl_key)\n+\t\t\tgoto nla_put_failure;\n+\n+\t\tNLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],\n+\t\t\tparams->wep_key[i]);\n+\t\tif (params->wep_key_len[i] == 5)\n+\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n+\t\telse\n+\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n+\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n+\n+\t\tNLA_PUT_U8(msg, NL80211_KEY_IDX, i);\n+\n+\t\tif (i == params->wep_tx_keyidx)\n+\t\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);\n+\n+\t\tnla_nest_end(msg, nl_key);\n+\t}\n+\tnla_nest_end(msg, nl_keys);\n+\n+\treturn 0;\n+\n+nla_put_failure:\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int wpa_driver_capwap_mlme(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t   const u8 *addr, int cmd, u16 reason_code,\n+\t\t\t\t   int local_state_change)\n+{\n+\tint ret = -1;\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, cmd);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);\n+\tif (addr)\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\tif (local_state_change)\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_dbg(drv->ctx, MSG_DEBUG,\n+\t\t\t\"capwap: MLME command failed: reason=%u ret=%d (%s)\",\n+\t\t\treason_code, ret, strerror(-ret));\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_disconnect(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\t int reason_code)\n+{\n+\twpa_printf(MSG_DEBUG, \"%s(reason_code=%d)\", __func__, reason_code);\n+\tdrv->associated = 0;\n+\tdrv->ignore_next_local_disconnect = 0;\n+\t/* Disconnect command doesn't need BSSID - it uses cached value */\n+\treturn wpa_driver_capwap_mlme(drv, NULL, NL80211_CMD_DISCONNECT,\n+\t\t\t\t       reason_code, 0);\n+}\n+\n+\n+static int wpa_driver_capwap_deauthenticate(struct i802_bss *bss,\n+\t\t\t\t\t     const u8 *addr, int reason_code)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))\n+\t\treturn wpa_driver_capwap_disconnect(drv, reason_code);\n+\twpa_printf(MSG_DEBUG, \"%s(addr=\" MACSTR \" reason_code=%d)\",\n+\t\t   __func__, MAC2STR(addr), reason_code);\n+\tdrv->associated = 0;\n+\tif (drv->nlmode == NL80211_IFTYPE_ADHOC)\n+\t\treturn capwap_leave_ibss(drv);\n+\treturn wpa_driver_capwap_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,\n+\t\t\t\t       reason_code, 0);\n+}\n+\n+\n+static void capwap_copy_auth_params(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t     struct wpa_driver_auth_params *params)\n+{\n+\tint i;\n+\n+\tdrv->auth_freq = params->freq;\n+\tdrv->auth_alg = params->auth_alg;\n+\tdrv->auth_wep_tx_keyidx = params->wep_tx_keyidx;\n+\tdrv->auth_local_state_change = params->local_state_change;\n+\tdrv->auth_p2p = params->p2p;\n+\n+\tif (params->bssid)\n+\t\tos_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);\n+\telse\n+\t\tos_memset(drv->auth_bssid_, 0, ETH_ALEN);\n+\n+\tif (params->ssid) {\n+\t\tos_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);\n+\t\tdrv->auth_ssid_len = params->ssid_len;\n+\t} else\n+\t\tdrv->auth_ssid_len = 0;\n+\n+\n+\tos_free(drv->auth_ie);\n+\tdrv->auth_ie = NULL;\n+\tdrv->auth_ie_len = 0;\n+\tif (params->ie) {\n+\t\tdrv->auth_ie = os_malloc(params->ie_len);\n+\t\tif (drv->auth_ie) {\n+\t\t\tos_memcpy(drv->auth_ie, params->ie, params->ie_len);\n+\t\t\tdrv->auth_ie_len = params->ie_len;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < 4; i++) {\n+\t\tif (params->wep_key[i] && params->wep_key_len[i] &&\n+\t\t    params->wep_key_len[i] <= 16) {\n+\t\t\tos_memcpy(drv->auth_wep_key[i], params->wep_key[i],\n+\t\t\t\t  params->wep_key_len[i]);\n+\t\t\tdrv->auth_wep_key_len[i] = params->wep_key_len[i];\n+\t\t} else\n+\t\t\tdrv->auth_wep_key_len[i] = 0;\n+\t}\n+}\n+\n+\n+static int wpa_driver_capwap_authenticate(\n+\tstruct i802_bss *bss, struct wpa_driver_auth_params *params)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret = -1, i;\n+\tstruct nl_msg *msg;\n+\tenum nl80211_auth_type type;\n+\tenum nl80211_iftype nlmode;\n+\tint count = 0;\n+\tint is_retry;\n+\n+\tis_retry = drv->retry_auth;\n+\tdrv->retry_auth = 0;\n+\n+\tdrv->associated = 0;\n+\tos_memset(drv->auth_bssid, 0, ETH_ALEN);\n+\t/* FIX: IBSS mode */\n+\tnlmode = params->p2p ?\n+\t\tNL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;\n+\tif (drv->nlmode != nlmode &&\n+\t    wpa_driver_capwap_set_mode(bss, nlmode) < 0)\n+\t\treturn -1;\n+\n+retry:\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Authenticate (ifindex=%d)\",\n+\t\t   drv->ifindex);\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);\n+\n+\tfor (i = 0; i < 4; i++) {\n+\t\tif (!params->wep_key[i])\n+\t\t\tcontinue;\n+\t\twpa_driver_capwap_set_key(bss->ifname, bss, WPA_ALG_WEP,\n+\t\t\t\t\t   NULL, i,\n+\t\t\t\t\t   i == params->wep_tx_keyidx, NULL, 0,\n+\t\t\t\t\t   params->wep_key[i],\n+\t\t\t\t\t   params->wep_key_len[i]);\n+\t\tif (params->wep_tx_keyidx != i)\n+\t\t\tcontinue;\n+\t\tif (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,\n+\t\t\t       params->wep_key[i], params->wep_key_len[i])) {\n+\t\t\tnlmsg_free(msg);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tif (params->bssid) {\n+\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n+\t\t\t   MAC2STR(params->bssid));\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n+\t}\n+\tif (params->freq) {\n+\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n+\t}\n+\tif (params->ssid) {\n+\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n+\t\t\t\t  params->ssid, params->ssid_len);\n+\t\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n+\t\t\tparams->ssid);\n+\t}\n+\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->ie, params->ie_len);\n+\tif (params->ie)\n+\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie);\n+\tif (params->sae_data) {\n+\t\twpa_hexdump(MSG_DEBUG, \"  * SAE data\", params->sae_data,\n+\t\t\t    params->sae_data_len);\n+\t\tNLA_PUT(msg, NL80211_ATTR_SAE_DATA, params->sae_data_len,\n+\t\t\tparams->sae_data);\n+\t}\n+\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n+\t\ttype = NL80211_AUTHTYPE_OPEN_SYSTEM;\n+\telse if (params->auth_alg & WPA_AUTH_ALG_SHARED)\n+\t\ttype = NL80211_AUTHTYPE_SHARED_KEY;\n+\telse if (params->auth_alg & WPA_AUTH_ALG_LEAP)\n+\t\ttype = NL80211_AUTHTYPE_NETWORK_EAP;\n+\telse if (params->auth_alg & WPA_AUTH_ALG_FT)\n+\t\ttype = NL80211_AUTHTYPE_FT;\n+\telse if (params->auth_alg & WPA_AUTH_ALG_SAE)\n+\t\ttype = NL80211_AUTHTYPE_SAE;\n+\telse\n+\t\tgoto nla_put_failure;\n+\twpa_printf(MSG_DEBUG, \"  * Auth Type %d\", type);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);\n+\tif (params->local_state_change) {\n+\t\twpa_printf(MSG_DEBUG, \"  * Local state change only\");\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_dbg(drv->ctx, MSG_DEBUG,\n+\t\t\t\"capwap: MLME command failed (auth): ret=%d (%s)\",\n+\t\t\tret, strerror(-ret));\n+\t\tcount++;\n+\t\tif (ret == -EALREADY && count == 1 && params->bssid &&\n+\t\t    !params->local_state_change) {\n+\t\t\t/*\n+\t\t\t * mac80211 does not currently accept new\n+\t\t\t * authentication if we are already authenticated. As a\n+\t\t\t * workaround, force deauthentication and try again.\n+\t\t\t */\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Retry authentication \"\n+\t\t\t\t   \"after forced deauthentication\");\n+\t\t\twpa_driver_capwap_deauthenticate(\n+\t\t\t\tbss, params->bssid,\n+\t\t\t\tWLAN_REASON_PREV_AUTH_NOT_VALID);\n+\t\t\tnlmsg_free(msg);\n+\t\t\tgoto retry;\n+\t\t}\n+\n+\t\tif (ret == -ENOENT && params->freq && !is_retry) {\n+\t\t\t/*\n+\t\t\t * cfg80211 has likely expired the BSS entry even\n+\t\t\t * though it was previously available in our internal\n+\t\t\t * BSS table. To recover quickly, start a single\n+\t\t\t * channel scan on the specified channel.\n+\t\t\t */\n+\t\t\tstruct wpa_driver_scan_params scan;\n+\t\t\tint freqs[2];\n+\n+\t\t\tos_memset(&scan, 0, sizeof(scan));\n+\t\t\tscan.num_ssids = 1;\n+\t\t\tif (params->ssid) {\n+\t\t\t\tscan.ssids[0].ssid = params->ssid;\n+\t\t\t\tscan.ssids[0].ssid_len = params->ssid_len;\n+\t\t\t}\n+\t\t\tfreqs[0] = params->freq;\n+\t\t\tfreqs[1] = 0;\n+\t\t\tscan.freqs = freqs;\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Trigger single \"\n+\t\t\t\t   \"channel scan to refresh cfg80211 BSS \"\n+\t\t\t\t   \"entry\");\n+\t\t\tret = wpa_driver_capwap_scan(bss, &scan);\n+\t\t\tif (ret == 0) {\n+\t\t\t\tcapwap_copy_auth_params(drv, params);\n+\t\t\t\tdrv->scan_for_auth = 1;\n+\t\t\t}\n+\t\t} else if (is_retry) {\n+\t\t\t/*\n+\t\t\t * Need to indicate this with an event since the return\n+\t\t\t * value from the retry is not delivered to core code.\n+\t\t\t */\n+\t\t\tunion wpa_event_data event;\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Authentication retry \"\n+\t\t\t\t   \"failed\");\n+\t\t\tos_memset(&event, 0, sizeof(event));\n+\t\t\tos_memcpy(event.timeout_event.addr, drv->auth_bssid_,\n+\t\t\t\t  ETH_ALEN);\n+\t\t\twpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,\n+\t\t\t\t\t     &event);\n+\t\t}\n+\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+\twpa_printf(MSG_DEBUG, \"capwap: Authentication request send \"\n+\t\t   \"successfully\");\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_authenticate_retry(\n+\tstruct wpa_driver_capwap_data *drv)\n+{\n+\tstruct wpa_driver_auth_params params;\n+\tstruct i802_bss *bss = &drv->first_bss;\n+\tint i;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Try to authenticate again\");\n+\n+\tos_memset(&params, 0, sizeof(params));\n+\tparams.freq = drv->auth_freq;\n+\tparams.auth_alg = drv->auth_alg;\n+\tparams.wep_tx_keyidx = drv->auth_wep_tx_keyidx;\n+\tparams.local_state_change = drv->auth_local_state_change;\n+\tparams.p2p = drv->auth_p2p;\n+\n+\tif (!is_zero_ether_addr(drv->auth_bssid_))\n+\t\tparams.bssid = drv->auth_bssid_;\n+\n+\tif (drv->auth_ssid_len) {\n+\t\tparams.ssid = drv->auth_ssid;\n+\t\tparams.ssid_len = drv->auth_ssid_len;\n+\t}\n+\n+\tparams.ie = drv->auth_ie;\n+\tparams.ie_len = drv->auth_ie_len;\n+\n+\tfor (i = 0; i < 4; i++) {\n+\t\tif (drv->auth_wep_key_len[i]) {\n+\t\t\tparams.wep_key[i] = drv->auth_wep_key[i];\n+\t\t\tparams.wep_key_len[i] = drv->auth_wep_key_len[i];\n+\t\t}\n+\t}\n+\n+\tdrv->retry_auth = 1;\n+\treturn wpa_driver_capwap_authenticate(bss, &params);\n+}\n+\n+\n+struct phy_info_arg {\n+\tu16 *num_modes;\n+\tstruct hostapd_hw_modes *modes;\n+};\n+\n+static int phy_info_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb_msg[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct phy_info_arg *phy_info = arg;\n+\n+\tstruct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];\n+\n+\tstruct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];\n+\tstatic struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {\n+\t\t[NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },\n+\t\t[NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },\n+\t\t[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },\n+\t\t[NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },\n+\t\t[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },\n+\t\t[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },\n+\t};\n+\n+\tstruct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];\n+\tstatic struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {\n+\t\t[NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },\n+\t\t[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG },\n+\t};\n+\n+\tstruct nlattr *nl_band;\n+\tstruct nlattr *nl_freq;\n+\tstruct nlattr *nl_rate;\n+\tint rem_band, rem_freq, rem_rate;\n+\tstruct hostapd_hw_modes *mode;\n+\tint idx, mode_is_set;\n+\n+\tnla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\tif (!tb_msg[NL80211_ATTR_WIPHY_BANDS])\n+\t\treturn NL_SKIP;\n+\n+\tnla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {\n+\t\tmode = os_realloc_array(phy_info->modes,\n+\t\t\t\t\t*phy_info->num_modes + 1,\n+\t\t\t\t\tsizeof(*mode));\n+\t\tif (!mode)\n+\t\t\treturn NL_SKIP;\n+\t\tphy_info->modes = mode;\n+\n+\t\tmode_is_set = 0;\n+\n+\t\tmode = &phy_info->modes[*(phy_info->num_modes)];\n+\t\tmemset(mode, 0, sizeof(*mode));\n+\t\tmode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN;\n+\t\t*(phy_info->num_modes) += 1;\n+\n+\t\tnla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),\n+\t\t\t  nla_len(nl_band), NULL);\n+\n+\t\tif (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {\n+\t\t\tmode->ht_capab = nla_get_u16(\n+\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_CAPA]);\n+\t\t}\n+\n+\t\tif (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) {\n+\t\t\tmode->a_mpdu_params |= nla_get_u8(\n+\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) &\n+\t\t\t\t0x03;\n+\t\t}\n+\n+\t\tif (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) {\n+\t\t\tmode->a_mpdu_params |= nla_get_u8(\n+\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) <<\n+\t\t\t\t2;\n+\t\t}\n+\n+\t\tif (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] &&\n+\t\t    nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])) {\n+\t\t\tu8 *mcs;\n+\t\t\tmcs = nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);\n+\t\t\tos_memcpy(mode->mcs_set, mcs, 16);\n+\t\t}\n+\n+\t\tif (tb_band[NL80211_BAND_ATTR_VHT_CAPA]) {\n+\t\t\tmode->vht_capab = nla_get_u32(\n+\t\t\t\ttb_band[NL80211_BAND_ATTR_VHT_CAPA]);\n+\t\t}\n+\n+\t\tif (tb_band[NL80211_BAND_ATTR_VHT_MCS_SET] &&\n+\t\t    nla_len(tb_band[NL80211_BAND_ATTR_VHT_MCS_SET])) {\n+\t\t\tu8 *mcs;\n+\t\t\tmcs = nla_data(tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);\n+\t\t\tos_memcpy(mode->vht_mcs_set, mcs, 8);\n+\t\t}\n+\n+\t\tnla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {\n+\t\t\tnla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),\n+\t\t\t\t  nla_len(nl_freq), freq_policy);\n+\t\t\tif (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])\n+\t\t\t\tcontinue;\n+\t\t\tmode->num_channels++;\n+\t\t}\n+\n+\t\tmode->channels = os_calloc(mode->num_channels,\n+\t\t\t\t\t   sizeof(struct hostapd_channel_data));\n+\t\tif (!mode->channels)\n+\t\t\treturn NL_SKIP;\n+\n+\t\tidx = 0;\n+\n+\t\tnla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {\n+\t\t\tnla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),\n+\t\t\t\t  nla_len(nl_freq), freq_policy);\n+\t\t\tif (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])\n+\t\t\t\tcontinue;\n+\n+\t\t\tmode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);\n+\t\t\tmode->channels[idx].flag = 0;\n+\n+\t\t\tif (!mode_is_set) {\n+\t\t\t\t/* crude heuristic */\n+\t\t\t\tif (mode->channels[idx].freq < 4000)\n+\t\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n+\t\t\t\telse if (mode->channels[idx].freq > 50000)\n+\t\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211AD;\n+\t\t\t\telse\n+\t\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211A;\n+\t\t\t\tmode_is_set = 1;\n+\t\t\t}\n+\n+\t\t\tswitch (mode->mode) {\n+\t\t\tcase HOSTAPD_MODE_IEEE80211AD:\n+\t\t\t\tmode->channels[idx].chan =\n+\t\t\t\t\t(mode->channels[idx].freq - 56160) /\n+\t\t\t\t\t2160;\n+\t\t\t\tbreak;\n+\t\t\tcase HOSTAPD_MODE_IEEE80211A:\n+\t\t\t\tmode->channels[idx].chan =\n+\t\t\t\t\tmode->channels[idx].freq / 5 - 1000;\n+\t\t\t\tbreak;\n+\t\t\tcase HOSTAPD_MODE_IEEE80211B:\n+\t\t\tcase HOSTAPD_MODE_IEEE80211G:\n+\t\t\t\tif (mode->channels[idx].freq == 2484)\n+\t\t\t\t\tmode->channels[idx].chan = 14;\n+\t\t\t\telse\n+\t\t\t\t\tmode->channels[idx].chan =\n+\t\t\t\t\t\t(mode->channels[idx].freq -\n+\t\t\t\t\t\t 2407) / 5;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])\n+\t\t\t\tmode->channels[idx].flag |=\n+\t\t\t\t\tHOSTAPD_CHAN_DISABLED;\n+\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])\n+\t\t\t\tmode->channels[idx].flag |=\n+\t\t\t\t\tHOSTAPD_CHAN_PASSIVE_SCAN;\n+\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])\n+\t\t\t\tmode->channels[idx].flag |=\n+\t\t\t\t\tHOSTAPD_CHAN_NO_IBSS;\n+\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])\n+\t\t\t\tmode->channels[idx].flag |=\n+\t\t\t\t\tHOSTAPD_CHAN_RADAR;\n+\n+\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] &&\n+\t\t\t    !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])\n+\t\t\t\tmode->channels[idx].max_tx_power =\n+\t\t\t\t\tnla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100;\n+\n+\t\t\tidx++;\n+\t\t}\n+\n+\t\tnla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {\n+\t\t\tnla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),\n+\t\t\t\t  nla_len(nl_rate), rate_policy);\n+\t\t\tif (!tb_rate[NL80211_BITRATE_ATTR_RATE])\n+\t\t\t\tcontinue;\n+\t\t\tmode->num_rates++;\n+\t\t}\n+\n+\t\tmode->rates = os_calloc(mode->num_rates, sizeof(int));\n+\t\tif (!mode->rates)\n+\t\t\treturn NL_SKIP;\n+\n+\t\tidx = 0;\n+\n+\t\tnla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {\n+\t\t\tnla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),\n+\t\t\t\t  nla_len(nl_rate), rate_policy);\n+\t\t\tif (!tb_rate[NL80211_BITRATE_ATTR_RATE])\n+\t\t\t\tcontinue;\n+\t\t\tmode->rates[idx] = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]);\n+\n+\t\t\t/* crude heuristic */\n+\t\t\tif (mode->mode == HOSTAPD_MODE_IEEE80211B &&\n+\t\t\t    mode->rates[idx] > 200)\n+\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211G;\n+\n+\t\t\tidx++;\n+\t\t}\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+static struct hostapd_hw_modes *\n+wpa_driver_capwap_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes)\n+{\n+\tu16 m;\n+\tstruct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;\n+\tint i, mode11g_idx = -1;\n+\tint j;\n+\n+\t/* If only 802.11g mode is included, use it to construct matching\n+\t * 802.11b mode data. */\n+\n+\tfor (m = 0; m < *num_modes; m++) {\n+\t\twpa_printf(MSG_DEBUG,\"*** 2.2 %d\\n\",m);\n+\t\tif (modes[m].mode == HOSTAPD_MODE_IEEE80211B)\n+\t\t\treturn modes; /* 802.11b already included */\n+\t\tif (modes[m].mode == HOSTAPD_MODE_IEEE80211G)\n+\t\t\tmode11g_idx = m;\n+\t}\n+\n+\tif (mode11g_idx < 0)\n+\t\treturn modes; /* 2.4 GHz band not supported at all */\n+\n+\tnmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes));\n+\tif (nmodes == NULL)\n+\t\treturn modes; /* Could not add 802.11b mode */\n+\n+\tmode = &nmodes[*num_modes];\n+\tos_memset(mode, 0, sizeof(*mode));\n+\t(*num_modes)++;\n+\tmodes = nmodes;\n+\n+\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n+\n+\tmode11g = &modes[mode11g_idx];\n+\tmode->num_channels = mode11g->num_channels;\n+\tmode->channels = os_malloc(mode11g->num_channels *\n+\t\t\t\t   sizeof(struct hostapd_channel_data));\n+\tif (mode->channels == NULL) {\n+\t\t(*num_modes)--;\n+\t\treturn modes; /* Could not add 802.11b mode */\n+\t}\n+\tos_memcpy(mode->channels, mode11g->channels,\n+\t\t  mode11g->num_channels * sizeof(struct hostapd_channel_data));\n+\n+\tmode->num_rates = 0;\n+\tmode->rates = os_malloc(4 * sizeof(int));\n+\tif (mode->rates == NULL) {\n+\t\tos_free(mode->channels);\n+\t\t(*num_modes)--;\n+\t\treturn modes; /* Could not add 802.11b mode */\n+\t}\n+\n+\tfor (i = 0; i < mode11g->num_rates; i++) {\n+\t\tif (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&\n+\t\t    mode11g->rates[i] != 55 && mode11g->rates[i] != 110)\n+\t\t\tcontinue;\n+\t\tmode->rates[mode->num_rates] = mode11g->rates[i];\n+\t\tmode->num_rates++;\n+\t\tif (mode->num_rates == 4)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (mode->num_rates == 0) {\n+\t\tos_free(mode->channels);\n+\t\tos_free(mode->rates);\n+\t\t(*num_modes)--;\n+\t\treturn modes; /* No 802.11b rates */\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Added 802.11b mode based on 802.11g information\");\n+\twpa_printf(MSG_DEBUG,\"*** Num_channels:%d Num_rates:%d capab:%d flags:%d MODE:%d mpdu:%02X\",modes->num_channels,modes->num_rates,modes->ht_capab,modes->flags,modes->mode,modes->a_mpdu_params);\n+\n+\tfor(j=0;j < 16;j++){\n+\t\twpa_printf(MSG_DEBUG,\"%02X \",modes->mcs_set[j]);\n+\t}\n+\n+\tfor(j=0;j < modes->num_channels;j++){\n+\t\twpa_printf(MSG_DEBUG,\"*** %d freq:%d flag:%d chan:%d freq:%d maxPower:%02X \",j,modes->channels[j].freq,modes->channels[j].flag,modes->channels[j].chan,modes->channels[j].freq,modes->channels[j].max_tx_power);\n+\t}\n+\tfor(j=0;j < modes->num_rates;j++){\n+\t\twpa_printf(MSG_DEBUG,\"*** %d rate:%d  \",j,modes->rates[j]);\n+\t}\n+\n+\treturn modes;\n+}\n+\n+\n+static void capwap_set_ht40_mode(struct hostapd_hw_modes *mode, int start,\n+\t\t\t\t  int end)\n+{\n+\tint c;\n+\n+\tfor (c = 0; c < mode->num_channels; c++) {\n+\t\tstruct hostapd_channel_data *chan = &mode->channels[c];\n+\t\tif (chan->freq - 10 >= start && chan->freq + 10 <= end)\n+\t\t\tchan->flag |= HOSTAPD_CHAN_HT40;\n+\t}\n+}\n+\n+\n+static void capwap_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,\n+\t\t\t\t      int end)\n+{\n+\tint c;\n+\n+\tfor (c = 0; c < mode->num_channels; c++) {\n+\t\tstruct hostapd_channel_data *chan = &mode->channels[c];\n+\t\tif (!(chan->flag & HOSTAPD_CHAN_HT40))\n+\t\t\tcontinue;\n+\t\tif (chan->freq - 30 >= start && chan->freq - 10 <= end)\n+\t\t\tchan->flag |= HOSTAPD_CHAN_HT40MINUS;\n+\t\tif (chan->freq + 10 >= start && chan->freq + 30 <= end)\n+\t\t\tchan->flag |= HOSTAPD_CHAN_HT40PLUS;\n+\t}\n+}\n+\n+\n+static void capwap_reg_rule_ht40(struct nlattr *tb[],\n+\t\t\t\t  struct phy_info_arg *results)\n+{\n+\tu32 start, end, max_bw;\n+\tu16 m;\n+\n+\tif (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||\n+\t    tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||\n+\t    tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)\n+\t\treturn;\n+\n+\tstart = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;\n+\tend = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;\n+\tmax_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: %u-%u @ %u MHz\",\n+\t\t   start, end, max_bw);\n+\tif (max_bw < 40)\n+\t\treturn;\n+\n+\tfor (m = 0; m < *results->num_modes; m++) {\n+\t\tif (!(results->modes[m].ht_capab &\n+\t\t      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))\n+\t\t\tcontinue;\n+\t\tcapwap_set_ht40_mode(&results->modes[m], start, end);\n+\t}\n+}\n+\n+\n+static void capwap_reg_rule_sec(struct nlattr *tb[],\n+\t\t\t\t struct phy_info_arg *results)\n+{\n+\tu32 start, end, max_bw;\n+\tu16 m;\n+\n+\tif (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||\n+\t    tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||\n+\t    tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)\n+\t\treturn;\n+\n+\tstart = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;\n+\tend = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;\n+\tmax_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;\n+\n+\tif (max_bw < 20)\n+\t\treturn;\n+\n+\tfor (m = 0; m < *results->num_modes; m++) {\n+\t\tif (!(results->modes[m].ht_capab &\n+\t\t      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))\n+\t\t\tcontinue;\n+\t\tcapwap_set_ht40_mode_sec(&results->modes[m], start, end);\n+\t}\n+}\n+\n+\n+static int capwap_get_reg(struct nl_msg *msg, void *arg)\n+{\n+\tstruct phy_info_arg *results = arg;\n+\tstruct nlattr *tb_msg[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct nlattr *nl_rule;\n+\tstruct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];\n+\tint rem_rule;\n+\tstatic struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {\n+\t\t[NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },\n+\t\t[NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },\n+\t\t[NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },\n+\t\t[NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },\n+\t\t[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },\n+\t\t[NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },\n+\t};\n+\n+\tnla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\tif (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||\n+\t    !tb_msg[NL80211_ATTR_REG_RULES]) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: No regulatory information \"\n+\t\t\t   \"available\");\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Regulatory information - country=%s\",\n+\t\t   (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));\n+\n+\tnla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)\n+\t{\n+\t\tnla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,\n+\t\t\t  nla_data(nl_rule), nla_len(nl_rule), reg_policy);\n+\t\tcapwap_reg_rule_ht40(tb_rule, results);\n+\t}\n+\n+\tnla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)\n+\t{\n+\t\tnla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,\n+\t\t\t  nla_data(nl_rule), nla_len(nl_rule), reg_policy);\n+\t\tcapwap_reg_rule_sec(tb_rule, results);\n+\t}\n+\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int capwap_set_ht40_flags(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t  struct phy_info_arg *results)\n+{\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_REG);\n+\treturn send_and_recv_msgs(drv, msg, capwap_get_reg, results);\n+}\n+\n+\n+static struct hostapd_hw_modes *\n+AC_wpa_driver_capwap_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)\n+{\n+\tint rate_arrays[8];\n+\tint num_rates;\n+\tint num_modes1;\n+\tint i;\n+\n+\tnum_rates = capability_get_rates(rate_arrays);\n+\tnum_modes1 = capability_get_num_modes();\n+\n+\tstruct hostapd_hw_modes *mode;\n+\tint clen, rlen;\n+\tconst short chan2freq[14] = {\n+\t\t2412, 2417, 2422, 2427, 2432, 2437, 2442,\n+\t\t2447, 2452, 2457, 2462, 2467, 2472, 2484\n+        };\n+\n+\n+\t*flags = 0;\n+\tmode = os_zalloc(sizeof(struct hostapd_hw_modes));\n+\tif (mode == NULL)\n+\t\treturn NULL;\n+\n+\t*num_modes = 1;\n+\n+\tif(capability_is_B()){\n+\t\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n+\t}else{\n+\t\twpa_printf(MSG_ERROR, \"ERROR AC_wpa_driver_capwap_get_hw_feature_data\\n\");\n+\t\texit(1);\n+\t}\n+\n+\tmode->num_channels = capability_get_num_channels();\n+\tmode->num_rates = num_rates ;\n+\n+\tclen = mode->num_channels * sizeof(struct hostapd_channel_data);\n+\trlen = mode->num_rates * sizeof(int);\n+\n+\tmode->channels = os_zalloc(clen);\n+\tmode->rates = os_zalloc(rlen);\n+\tif (mode->channels == NULL || mode->rates == NULL) {\n+\t\tos_free(mode->channels);\n+\t\tos_free(mode->rates);\n+\t\tos_free(mode);\n+\t\treturn NULL;\n+\t}\n+\tfor (i = 0; i < mode->num_channels; i++) {\n+\t\tmode->channels[i].chan = i + 1;\n+\t\tmode->channels[i].freq = chan2freq[i];\n+\t\t/* TODO: Get allowed channel list from the driver */\n+\t\tif (i >= 11)\n+\t\t\tmode->channels[i].flag = HOSTAPD_CHAN_DISABLED;\n+\t}\n+\n+\tfor( i=0; i<mode->num_rates ; i++){\n+\t\tif( rate_arrays[i] < 0 )\n+\t\t\tmode->rates[i] = -1 * rate_arrays[i];\n+\t\telse\n+\t\t\tmode->rates[i] =  rate_arrays[i];\n+\t}\n+\n+\treturn mode;\n+\n+}\n+\n+static struct hostapd_hw_modes *\n+wpa_driver_capwap_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) {\n+\treturn AC_wpa_driver_capwap_get_hw_feature_data(priv,num_modes,flags);\n+}\n+\n+\n+static int wpa_driver_capwap_send_mntr(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t\tconst void *data, size_t len,\n+\t\t\t\t\tint encrypt, int noack)\n+{\n+\n+\twpa_printf(MSG_DEBUG, \"                                                                                 1.wpa_driver_capwap_send_frame \");\n+\tunsigned char buf[3000];\n+\n+\t__u8 rtap_hdr[] = {\n+\t\t0x00, 0x00, /* radiotap version */\n+\t\t0x0e, 0x00, /* radiotap length */\n+\t\t0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */\n+\t\tIEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */\n+\t\t0x00,       /* padding */\n+\t\t0x00, 0x00, /* RX and TX flags to indicate that */\n+\t\t0x00, 0x00, /* this is the injected frame directly */\n+\t};\n+\tstruct iovec iov[2] = {\n+\t\t{\n+\t\t\t.iov_base = &rtap_hdr,\n+\t\t\t.iov_len = sizeof(rtap_hdr),\n+\t\t},\n+\t\t{\n+\t\t\t.iov_base = (void *) data,\n+\t\t\t.iov_len = len,\n+\t\t}\n+\t};\n+\tstruct msghdr msg = {\n+\t\t.msg_name = NULL,\n+\t\t.msg_namelen = 0,\n+\t\t.msg_iov = iov,\n+\t\t.msg_iovlen = 2,\n+\t\t.msg_control = NULL,\n+\t\t.msg_controllen = 0,\n+\t\t.msg_flags = 0,\n+\t};\n+\tint res;\n+\tu16 txflags = 0;\n+\n+\tif (encrypt)\n+\t\trtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;\n+\n+\tif (noack)\n+\t\ttxflags |= IEEE80211_RADIOTAP_F_TX_NOACK;\n+\tWPA_PUT_LE16(&rtap_hdr[12], txflags);\n+\n+\tmemcpy(buf,(u8 *)(data),len);\n+\t//AC_handle_send_data_to_WTP(buf, len, generic_ac_info.own_mac_addr);\n+\n+\t//Switch_Mac_Address_AC_to_WTP(buf, generic_ac_info.own_mac_addr);\n+\tipc_send_80211_to_wtp(generic_ac_info.fd_ipc, buf, len);\n+\t\n+\treturn 0;\n+\n+\tres = sendmsg(drv->monitor_sock, &msg, 0);\n+\tif (res < 0) {\n+\t\twpa_printf(MSG_INFO, \"capwap: sendmsg: %s\", strerror(errno));\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_send_frame(struct i802_bss *bss,\n+\t\t\t\t\t const void *data, size_t len,\n+\t\t\t\t\t int encrypt, int noack,\n+\t\t\t\t\t unsigned int freq, int no_cck,\n+\t\t\t\t\t int offchanok, unsigned int wait_time)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tu64 cookie;\n+\n+\tif (freq == 0)\n+\t\tfreq = bss->freq;\n+\n+\tif (drv->use_monitor)\n+\t\treturn wpa_driver_capwap_send_mntr(drv, data, len,\n+\t\t\t\t\t\t    encrypt, noack);\n+\n+\treturn capwap_send_frame_cmd(bss, freq, wait_time, data, len,\n+\t\t\t\t      &cookie, no_cck, noack, offchanok);\n+}\n+\n+\n+static int wpa_driver_capwap_send_mlme(struct i802_bss *bss, const u8 *data,\n+\t\t\t\t\tsize_t data_len, int noack,\n+\t\t\t\t\tunsigned int freq, int no_cck,\n+\t\t\t\t\tint offchanok,\n+\t\t\t\t\tunsigned int wait_time)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct ieee80211_mgmt *mgmt;\n+\tint encrypt = 1;\n+\tu16 fc;\n+\n+\tmgmt = (struct ieee80211_mgmt *) data;\n+\tfc = le_to_host16(mgmt->frame_control);\n+\n+\tif (is_sta_interface(drv->nlmode) &&\n+\t    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&\n+\t    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {\n+\t\t/*\n+\t\t * The use of last_mgmt_freq is a bit of a hack,\n+\t\t * but it works due to the single-threaded nature\n+\t\t * of wpa_supplicant.\n+\t\t */\n+\t\tif (freq == 0)\n+\t\t\tfreq = drv->last_mgmt_freq;\n+\t\treturn capwap_send_frame_cmd(bss, freq, 0,\n+\t\t\t\t\t      data, data_len, NULL, 1, noack,\n+\t\t\t\t\t      1);\n+\t}\n+\n+\tif (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {\n+\t\tif (freq == 0)\n+\t\t\tfreq = bss->freq;\n+\t\treturn capwap_send_frame_cmd(bss, freq,\n+\t\t\t\t\t      (int) freq == bss->freq ? 0 :\n+\t\t\t\t\t      wait_time,\n+\t\t\t\t\t      data, data_len,\n+\t\t\t\t\t      &drv->send_action_cookie,\n+\t\t\t\t\t      no_cck, noack, offchanok);\n+\t}\n+\n+\tif (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&\n+\t    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {\n+\t\t/*\n+\t\t * Only one of the authentication frame types is encrypted.\n+\t\t * In order for static WEP encryption to work properly (i.e.,\n+\t\t * to not encrypt the frame), we need to tell mac80211 about\n+\t\t * the frames that must not be encrypted.\n+\t\t */\n+\t\tu16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);\n+\t\tu16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);\n+\t\tif (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)\n+\t\t\tencrypt = 0;\n+\t}\n+\n+\treturn wpa_driver_capwap_send_frame(bss, data, data_len, encrypt,\n+\t\t\t\t\t     noack, freq, no_cck, offchanok,\n+\t\t\t\t\t     wait_time);\n+}\n+\n+\n+int round1=0;\n+\n+static int capwap_set_bss(struct i802_bss *bss, int cts, int preamble,\n+\t\t\t   int slot, int ht_opmode, int ap_isolate,\n+\t\t\t   int *basic_rates)\n+{\n+\twpa_printf(MSG_DEBUG,\"> capwap_set_bss\\n\");\n+\tif(round1)return 0;\n+\telse round1=1;\n+\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);\n+\n+\tif (cts >= 0)\n+\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);\n+\tif (preamble >= 0)\n+\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);\n+\tif (slot >= 0)\n+\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);\n+\tif (ht_opmode >= 0)\n+\t\tNLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);\n+\tif (ap_isolate >= 0)\n+\t\tNLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate);\n+\n+\tif (basic_rates) {\n+\t\tu8 rates[NL80211_MAX_SUPP_RATES];\n+\t\tu8 rates_len = 0;\n+\t\tint i;\n+\n+\t\tfor (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0;\n+\t\t     i++)\n+\t\t\trates[rates_len++] = basic_rates[i] / 5;\n+\n+\t\tNLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);\n+\t}\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n+\n+\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int wpa_driver_capwap_set_ap(void *priv,\n+\t\t\t\t     struct wpa_driver_ap_params *params)\n+{\n+\twpa_printf(MSG_DEBUG, \"> wpa_driver_capwap_set_ap \\n\");\n+ \tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tu8 cmd = NL80211_CMD_NEW_BEACON;\n+\tint ret;\n+\tint beacon_set;\n+\tint ifindex = if_nametoindex(bss->ifname);\n+\tint num_suites;\n+\tu32 suites[10];\n+\tu32 ver;\n+\n+\tbeacon_set = bss->beacon_set;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Set beacon (beacon_set=%d)\",\n+\t\t   beacon_set);\n+\tif (beacon_set)\n+\t\tcmd = NL80211_CMD_SET_BEACON;\n+\n+\tcapwap_cmd(drv, msg, 0, cmd);\n+\tNLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);\n+\tNLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);\n+\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n+\t\tparams->ssid);\n+\tif (params->proberesp && params->proberesp_len)\n+\t\tNLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,\n+\t\t\tparams->proberesp);\n+\tswitch (params->hide_ssid) {\n+\tcase NO_SSID_HIDING:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n+\t\t\t    NL80211_HIDDEN_SSID_NOT_IN_USE);\n+\t\tbreak;\n+\tcase HIDDEN_SSID_ZERO_LEN:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n+\t\t\t    NL80211_HIDDEN_SSID_ZERO_LEN);\n+\t\tbreak;\n+\tcase HIDDEN_SSID_ZERO_CONTENTS:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n+\t\t\t    NL80211_HIDDEN_SSID_ZERO_CONTENTS);\n+\t\tbreak;\n+\t}\n+\tif (params->privacy)\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);\n+\tif ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==\n+\t    (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {\n+\t\t/* Leave out the attribute */\n+\t} else if (params->auth_algs & WPA_AUTH_ALG_SHARED)\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,\n+\t\t\t    NL80211_AUTHTYPE_SHARED_KEY);\n+\telse\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,\n+\t\t\t    NL80211_AUTHTYPE_OPEN_SYSTEM);\n+\n+\tver = 0;\n+\tif (params->wpa_version & WPA_PROTO_WPA)\n+\t\tver |= NL80211_WPA_VERSION_1;\n+\tif (params->wpa_version & WPA_PROTO_RSN)\n+\t\tver |= NL80211_WPA_VERSION_2;\n+\tif (ver)\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);\n+\n+\tnum_suites = 0;\n+\tif (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)\n+\t\tsuites[num_suites++] = WLAN_AKM_SUITE_8021X;\n+\tif (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)\n+\t\tsuites[num_suites++] = WLAN_AKM_SUITE_PSK;\n+\tif (num_suites) {\n+\t\tNLA_PUT(msg, NL80211_ATTR_AKM_SUITES,\n+\t\t\tnum_suites * sizeof(u32), suites);\n+\t}\n+\n+\tif (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X &&\n+\t    params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40))\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);\n+\n+\tnum_suites = 0;\n+\tif (params->pairwise_ciphers & WPA_CIPHER_CCMP)\n+\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;\n+\tif (params->pairwise_ciphers & WPA_CIPHER_GCMP)\n+\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;\n+\tif (params->pairwise_ciphers & WPA_CIPHER_TKIP)\n+\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;\n+\tif (params->pairwise_ciphers & WPA_CIPHER_WEP104)\n+\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;\n+\tif (params->pairwise_ciphers & WPA_CIPHER_WEP40)\n+\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;\n+\tif (num_suites) {\n+\t\tNLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,\n+\t\t\tnum_suites * sizeof(u32), suites);\n+\t}\n+\n+\tswitch (params->group_cipher) {\n+\tcase WPA_CIPHER_CCMP:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n+\t\t\t    WLAN_CIPHER_SUITE_CCMP);\n+\t\tbreak;\n+\tcase WPA_CIPHER_GCMP:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n+\t\t\t    WLAN_CIPHER_SUITE_GCMP);\n+\t\tbreak;\n+\tcase WPA_CIPHER_TKIP:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n+\t\t\t    WLAN_CIPHER_SUITE_TKIP);\n+\t\tbreak;\n+\tcase WPA_CIPHER_WEP104:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n+\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n+\t\tbreak;\n+\tcase WPA_CIPHER_WEP40:\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n+\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n+\t\tbreak;\n+\t}\n+\n+\tif (params->beacon_ies) {\n+\t\tNLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),\n+\t\t\twpabuf_head(params->beacon_ies));\n+\t}\n+\tif (params->proberesp_ies) {\n+\t\tNLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,\n+\t\t\twpabuf_len(params->proberesp_ies),\n+\t\t\twpabuf_head(params->proberesp_ies));\n+\t}\n+\tif (params->assocresp_ies) {\n+\t\tNLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,\n+\t\t\twpabuf_len(params->assocresp_ies),\n+\t\t\twpabuf_head(params->assocresp_ies));\n+\t}\n+\n+\tif (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)  {\n+\t\tNLA_PUT_U16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,\n+\t\t\t    params->ap_max_inactivity);\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Beacon set failed: %d (%s)\",\n+\t\t\t   ret, strerror(-ret));\n+\t} else {\n+\t\tbss->beacon_set = 1;\n+\t\tcapwap_set_bss(bss, params->cts_protect, params->preamble,\n+\t\t\t\tparams->short_slot_time, params->ht_opmode,\n+\t\t\t\tparams->isolate, params->basic_rates);\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"=== (P) privacy: %d\\n\",params->privacy);\n+\twpa_printf(MSG_DEBUG, \"=== (T) short_slot_time: %d\\n\",params->short_slot_time);\n+\twpa_printf(MSG_DEBUG, \"=== (S) preamble: %d\\n\",params->preamble);\n+\n+\tprep_beacon(generic_ac_info.fd_ipc,drv->ctx,params);\n+\n+\t//ipc_send_ADD_WLAN(generic_ac_info.fd_ipc, params->ssid, params->ssid_len);\n+\n+\treturn ret;\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int wpa_driver_capwap_set_freq(struct i802_bss *bss,\n+\t\t\t\t       struct hostapd_freq_params *freq)\n+{\n+\twpa_printf(MSG_DEBUG,\"                                          1.wpa_driver_capwap_set_freq\\n\");\n+\treturn 0;\n+}\n+\n+\n+static u32 sta_flags_capwap(int flags)\n+{\n+\tu32 f = 0;\n+\n+\tif (flags & WPA_STA_AUTHORIZED)\n+\t\tf |= BIT(NL80211_STA_FLAG_AUTHORIZED);\n+\tif (flags & WPA_STA_WMM)\n+\t\tf |= BIT(NL80211_STA_FLAG_WME);\n+\tif (flags & WPA_STA_SHORT_PREAMBLE)\n+\t\tf |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);\n+\tif (flags & WPA_STA_MFP)\n+\t\tf |= BIT(NL80211_STA_FLAG_MFP);\n+\tif (flags & WPA_STA_TDLS_PEER)\n+\t\tf |= BIT(NL80211_STA_FLAG_TDLS_PEER);\n+\n+\treturn f;\n+}\n+\n+\n+static int wpa_driver_capwap_sta_add(void *priv,\n+\t\t\t\t      struct hostapd_sta_add_params *params)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg, *wme = NULL;\n+\tstruct nl80211_sta_flag_update upd;\n+\tint ret = -ENOBUFS;\n+\n+\tif ((params->flags & WPA_STA_TDLS_PEER) &&\n+\t    !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: %s STA \" MACSTR,\n+\t\t   params->set ? \"Set\" : \"Add\", MAC2STR(params->addr));\n+\tcapwap_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :\n+\t\t    NL80211_CMD_NEW_STATION);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);\n+\tNLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,\n+\t\tparams->supp_rates);\n+\twpa_hexdump(MSG_DEBUG, \"  * supported rates\", params->supp_rates,\n+\t\t    params->supp_rates_len);\n+\tif (!params->set) {\n+\t\twpa_printf(MSG_DEBUG, \"  * aid=%u\", params->aid);\n+\t\tNLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);\n+\t\twpa_printf(MSG_DEBUG, \"  * listen_interval=%u\",\n+\t\t\t   params->listen_interval);\n+\t\tNLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,\n+\t\t\t    params->listen_interval);\n+\t}\n+\tif (params->ht_capabilities) {\n+\t\twpa_hexdump(MSG_DEBUG, \"  * ht_capabilities\",\n+\t\t\t    (u8 *) params->ht_capabilities,\n+\t\t\t    sizeof(*params->ht_capabilities));\n+\t\tNLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,\n+\t\t\tsizeof(*params->ht_capabilities),\n+\t\t\tparams->ht_capabilities);\n+\t}\n+\n+\tif (params->vht_capabilities) {\n+\t\twpa_hexdump(MSG_DEBUG, \"  * vht_capabilities\",\n+\t\t\t    (u8 *) params->vht_capabilities,\n+\t\t\t    sizeof(*params->vht_capabilities));\n+\t\tNLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY,\n+\t\t\tsizeof(*params->vht_capabilities),\n+\t\t\tparams->vht_capabilities);\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"  * capability=0x%x\", params->capability);\n+\tNLA_PUT_U16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability);\n+\n+\tif (params->ext_capab) {\n+\t\twpa_hexdump(MSG_DEBUG, \"  * ext_capab\",\n+\t\t\t    params->ext_capab, params->ext_capab_len);\n+\t\tNLA_PUT(msg, NL80211_ATTR_STA_EXT_CAPABILITY,\n+\t\t\tparams->ext_capab_len, params->ext_capab);\n+\t}\n+\n+\tos_memset(&upd, 0, sizeof(upd));\n+\tupd.mask = sta_flags_capwap(params->flags);\n+\tupd.set = upd.mask;\n+\twpa_printf(MSG_DEBUG, \"  * flags set=0x%x mask=0x%x\",\n+\t\t   upd.set, upd.mask);\n+\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n+\n+\tif (params->flags & WPA_STA_WMM) {\n+\t\twme = nlmsg_alloc();\n+\t\tif (!wme)\n+\t\t\tgoto nla_put_failure;\n+\n+\t\twpa_printf(MSG_DEBUG, \"  * qosinfo=0x%x\", params->qosinfo);\n+\t\tNLA_PUT_U8(wme, NL80211_STA_WME_UAPSD_QUEUES,\n+\t\t\t\tparams->qosinfo & WMM_QOSINFO_STA_AC_MASK);\n+\t\tNLA_PUT_U8(wme, NL80211_STA_WME_MAX_SP,\n+\t\t\t\t(params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &\n+\t\t\t\tWMM_QOSINFO_STA_SP_MASK);\n+\t\tif (nla_put_nested(msg, NL80211_ATTR_STA_WME, wme) < 0)\n+\t\t\tgoto nla_put_failure;\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: NL80211_CMD_%s_STATION \"\n+\t\t\t   \"result: %d (%s)\", params->set ? \"SET\" : \"NEW\", ret,\n+\t\t\t   strerror(-ret));\n+\tif (ret == -EEXIST)\n+\t\tret = 0;\n+ nla_put_failure:\n+\tnlmsg_free(wme);\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_sta_remove(struct i802_bss *bss, const u8 *addr)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n+\t\t    if_nametoindex(bss->ifname));\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tif (ret == -ENOENT)\n+\t\treturn 0;\n+\treturn ret;\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static void capwap_remove_iface(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t int ifidx)\n+{\n+\tstruct nl_msg *msg;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Remove interface ifindex=%d\", ifidx);\n+\n+\t/* stop listening for EAPOL on this interface */\n+\tdel_ifidx(drv, ifidx);\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\tgoto nla_put_failure;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);\n+\n+\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n+\t\treturn;\n+\tmsg = NULL;\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\twpa_printf(MSG_ERROR, \"Failed to remove interface (ifidx=%d)\", ifidx);\n+}\n+\n+\n+static const char * capwap_iftype_str(enum nl80211_iftype mode)\n+{\n+\tswitch (mode) {\n+\tcase NL80211_IFTYPE_ADHOC:\n+\t\treturn \"ADHOC\";\n+\tcase NL80211_IFTYPE_STATION:\n+\t\treturn \"STATION\";\n+\tcase NL80211_IFTYPE_AP:\n+\t\treturn \"AP\";\n+\tcase NL80211_IFTYPE_MONITOR:\n+\t\treturn \"MONITOR\";\n+\tcase NL80211_IFTYPE_P2P_CLIENT:\n+\t\treturn \"P2P_CLIENT\";\n+\tcase NL80211_IFTYPE_P2P_GO:\n+\t\treturn \"P2P_GO\";\n+\tdefault:\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n+\n+static int capwap_create_iface_once(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t     const char *ifname,\n+\t\t\t\t     enum nl80211_iftype iftype,\n+\t\t\t\t     const u8 *addr, int wds)\n+{\n+\twpa_printf(MSG_DEBUG, \"# capwap_create_iface_once\\n\");\n+\tstruct nl_msg *msg, *flags = NULL;\n+\tint ifidx;\n+\tint ret = -ENOBUFS;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Create interface iftype %d (%s)\",\n+\t\t   iftype, capwap_iftype_str(iftype));\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);\n+\n+\tif (iftype == NL80211_IFTYPE_MONITOR) {\n+\t\tint err;\n+\n+\t\tflags = nlmsg_alloc();\n+\t\tif (!flags)\n+\t\t\tgoto nla_put_failure;\n+\n+\t\tNLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);\n+\n+\t\terr = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);\n+\n+\t\tnlmsg_free(flags);\n+\n+\t\tif (err)\n+\t\t\tgoto nla_put_failure;\n+\t} else if (wds) {\n+\t\tNLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+ nla_put_failure:\n+\t\tnlmsg_free(msg);\n+\t\twpa_printf(MSG_ERROR, \"Failed to create interface %s: %d (%s)\",\n+\t\t\t   ifname, ret, strerror(-ret));\n+\t\treturn ret;\n+\t}\n+\n+\tifidx = if_nametoindex(ifname);\n+\twpa_printf(MSG_DEBUG, \"capwap: New interface %s created: ifindex=%d\",\n+\t\t   ifname, ifidx);\n+\n+\t/* start listening for EAPOL on this interface */\n+ \twpa_printf(MSG_DEBUG, \"start listening for EAPOL on this interface\\n\");\t\n+\tadd_ifidx(drv, ifidx);\n+\n+\tif (addr && iftype != NL80211_IFTYPE_MONITOR &&\n+\t    linux_set_fake_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {\n+\t\tcapwap_remove_iface(drv, ifidx);\n+\t\treturn -1;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"#9 %d\\n\",ifidx);\n+\n+\treturn ifidx;\n+}\n+\n+\n+static int capwap_create_iface(struct wpa_driver_capwap_data *drv,\n+\t\t\t\tconst char *ifname, enum nl80211_iftype iftype,\n+\t\t\t\tconst u8 *addr, int wds)\n+{\n+\tint ret;\n+\n+\tret = capwap_create_iface_once(drv, ifname, iftype, addr, wds);\n+\n+\t/* if error occurred and interface exists already */\n+\tif (ret == -ENFILE && if_nametoindex(ifname)) {\n+\t\twpa_printf(MSG_INFO, \"Try to remove and re-create %s\", ifname);\n+\n+\t\t/* Try to remove the interface that was already there. */\n+\t\tcapwap_remove_iface(drv, if_nametoindex(ifname));\n+\n+\t\t/* Try to create the interface again */\n+\t\tret = capwap_create_iface_once(drv, ifname, iftype, addr,\n+\t\t\t\t\t\twds);\n+\t}\n+\n+\tif (ret >= 0 && is_p2p_interface(iftype))\n+\t\tcapwap_disable_11b_rates(drv, ret, 1);\n+\n+\treturn ret;\n+}\n+\n+\n+static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)\n+{\n+\tstruct ieee80211_hdr *hdr;\n+\tu16 fc;\n+\tunion wpa_event_data event;\n+\n+\thdr = (struct ieee80211_hdr *) buf;\n+\tfc = le_to_host16(hdr->frame_control);\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tevent.tx_status.type = WLAN_FC_GET_TYPE(fc);\n+\tevent.tx_status.stype = WLAN_FC_GET_STYPE(fc);\n+\tevent.tx_status.dst = hdr->addr1;\n+\tevent.tx_status.data = buf;\n+\tevent.tx_status.data_len = len;\n+\tevent.tx_status.ack = ok;\n+\twpa_supplicant_event(ctx, EVENT_TX_STATUS, &event);\n+}\n+\n+\n+static void from_unknown_sta(struct wpa_driver_capwap_data *drv,\n+\t\t\t     u8 *buf, size_t len)\n+{\n+\tstruct ieee80211_hdr *hdr = (void *)buf;\n+\tu16 fc;\n+\tunion wpa_event_data event;\n+\n+\tif (len < sizeof(*hdr))\n+\t\treturn;\n+\n+\tfc = le_to_host16(hdr->frame_control);\n+\n+\tos_memset(&event, 0, sizeof(event));\n+\tevent.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);\n+\tevent.rx_from_unknown.addr = hdr->addr2;\n+\tevent.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==\n+\t\t(WLAN_FC_FROMDS | WLAN_FC_TODS);\n+\twpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);\n+}\n+\n+\n+static void handle_frame(struct wpa_driver_capwap_data *drv,\n+\t\t\t u8 *buf, size_t len, int datarate, int ssi_signal)\n+{\n+\tstruct ieee80211_hdr *hdr;\n+\tu16 fc;\n+\tunion wpa_event_data event;\n+\n+\thdr = (struct ieee80211_hdr *) buf;\n+\tfc = le_to_host16(hdr->frame_control);\n+\n+\tswitch (WLAN_FC_GET_TYPE(fc)) {\n+\tcase WLAN_FC_TYPE_MGMT:\n+\t\tos_memset(&event, 0, sizeof(event));\n+\t\tevent.rx_mgmt.frame = buf;\n+\t\tevent.rx_mgmt.frame_len = len;\n+\t\tevent.rx_mgmt.datarate = datarate;\n+\t\tevent.rx_mgmt.ssi_signal = ssi_signal;\n+\t\twpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);\n+\t\tbreak;\n+\tcase WLAN_FC_TYPE_CTRL:\n+\t\t/* can only get here with PS-Poll frames */\n+\t\twpa_printf(MSG_DEBUG, \"CTRL\");\n+\t\tfrom_unknown_sta(drv, buf, len);\n+\t\tbreak;\n+\tcase WLAN_FC_TYPE_DATA:\n+\t\tfrom_unknown_sta(drv, buf, len);\n+\t\tbreak;\n+\t}\n+}\n+\n+\n+static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)\n+{\n+\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n+\tint len;\n+\tunsigned char buf[3000];\n+\tstruct ieee80211_radiotap_iterator iter;\n+\tint ret;\n+\tint datarate = 0, ssi_signal = 0;\n+\tint injected = 0, failed = 0, rxflags = 0;\n+\tlen = recv(sock, buf, sizeof(buf), 0);\n+\n+\tif (len < 0) {\n+\t\tperror(\"recv\");\n+\t\treturn;\n+\t}\n+\n+\tif (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {\n+\t\twpa_printf(MSG_DEBUG, \"received invalid radiotap frame\\n\");\n+\t\treturn;\n+\t}\n+\n+\twhile (1) {\n+\t\tret = ieee80211_radiotap_iterator_next(&iter);\n+\t\tif (ret == -ENOENT)\n+\t\t\tbreak;\n+\t\tif (ret) {\n+\t\t\twpa_printf(MSG_DEBUG, \"received invalid radiotap frame (%d)\\n\", ret);\n+\t\t\treturn;\n+\t\t}\n+\t\tswitch (iter.this_arg_index) {\n+\t\tcase IEEE80211_RADIOTAP_FLAGS:\n+\t\t\tif (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)\n+\t\t\t\tlen -= 4;\n+\t\t\tbreak;\n+\t\tcase IEEE80211_RADIOTAP_RX_FLAGS:\n+\t\t\trxflags = 1;\n+\t\t\tbreak;\n+\t\tcase IEEE80211_RADIOTAP_TX_FLAGS:\n+\t\t\tinjected = 1;\n+\t\t\tfailed = le_to_host16((*(uint16_t *) iter.this_arg)) &\n+\t\t\t\t\tIEEE80211_RADIOTAP_F_TX_FAIL;\n+\t\t\tbreak;\n+\t\tcase IEEE80211_RADIOTAP_DATA_RETRIES:\n+\t\t\tbreak;\n+\t\tcase IEEE80211_RADIOTAP_CHANNEL:\n+\t\t\t/* TODO: convert from freq/flags to channel number */\n+\t\t\tbreak;\n+\t\tcase IEEE80211_RADIOTAP_RATE:\n+\t\t\tdatarate = *iter.this_arg * 5;\n+\t\t\tbreak;\n+\t\tcase IEEE80211_RADIOTAP_DBM_ANTSIGNAL:\n+\t\t\tssi_signal = (s8) *iter.this_arg;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (rxflags && injected)\n+\t\treturn;\n+\n+\tif (!injected)\n+\t\thandle_frame(drv, buf + iter.max_length,\n+\t\t\t     len - iter.max_length, datarate, ssi_signal);\n+\telse\n+\t\thandle_tx_callback(drv->ctx, buf + iter.max_length,\n+\t\t\t\t   len - iter.max_length, !failed);\n+}\n+\n+\n+/*\n+ * we post-process the filter code later and rewrite\n+ * this to the offset to the last instruction\n+ */\n+#define PASS\t0xFF\n+#define FAIL\t0xFE\n+\n+static struct sock_filter msock_filter_insns[] = {\n+\t/*\n+\t * do a little-endian load of the radiotap length field\n+\t */\n+\t/* load lower byte into A */\n+\tBPF_STMT(BPF_LD  | BPF_B | BPF_ABS, 2),\n+\t/* put it into X (== index register) */\n+\tBPF_STMT(BPF_MISC| BPF_TAX, 0),\n+\t/* load upper byte into A */\n+\tBPF_STMT(BPF_LD  | BPF_B | BPF_ABS, 3),\n+\t/* left-shift it by 8 */\n+\tBPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8),\n+\t/* or with X */\n+\tBPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0),\n+\t/* put result into X */\n+\tBPF_STMT(BPF_MISC| BPF_TAX, 0),\n+\n+\t/*\n+\t * Allow management frames through, this also gives us those\n+\t * management frames that we sent ourselves with status\n+\t */\n+\t/* load the lower byte of the IEEE 802.11 frame control field */\n+\tBPF_STMT(BPF_LD  | BPF_B | BPF_IND, 0),\n+\t/* mask off frame type and version */\n+\tBPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF),\n+\t/* accept frame if it's both 0, fall through otherwise */\n+\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0),\n+\n+\t/*\n+\t * TODO: add a bit to radiotap RX flags that indicates\n+\t * that the sending station is not associated, then\n+\t * add a filter here that filters on our DA and that flag\n+\t * to allow us to deauth frames to that bad station.\n+\t *\n+\t * For now allow all To DS data frames through.\n+\t */\n+\t/* load the IEEE 802.11 frame control field */\n+\tBPF_STMT(BPF_LD  | BPF_H | BPF_IND, 0),\n+\t/* mask off frame type, version and DS status */\n+\tBPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03),\n+\t/* accept frame if version 0, type 2 and To DS, fall through otherwise\n+\t */\n+\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0),\n+\n+#if 0\n+\t/*\n+\t * drop non-data frames\n+\t */\n+\t/* load the lower byte of the frame control field */\n+\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 0),\n+\t/* mask off QoS bit */\n+\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x0c),\n+\t/* drop non-data frames */\n+\tBPF_JUMP(BPF_JMP  | BPF_JEQ | BPF_K, 8, 0, FAIL),\n+#endif\n+\t/* load the upper byte of the frame control field */\n+\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 1),\n+\t/* mask off toDS/fromDS */\n+\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x03),\n+\t/* accept WDS frames */\n+\tBPF_JUMP(BPF_JMP  | BPF_JEQ | BPF_K, 3, PASS, 0),\n+\n+\t/*\n+\t * add header length to index\n+\t */\n+\t/* load the lower byte of the frame control field */\n+\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 0),\n+\t/* mask off QoS bit */\n+\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x80),\n+\t/* right shift it by 6 to give 0 or 2 */\n+\tBPF_STMT(BPF_ALU  | BPF_RSH | BPF_K, 6),\n+\t/* add data frame header length */\n+\tBPF_STMT(BPF_ALU  | BPF_ADD | BPF_K, 24),\n+\t/* add index, was start of 802.11 header */\n+\tBPF_STMT(BPF_ALU  | BPF_ADD | BPF_X, 0),\n+\t/* move to index, now start of LL header */\n+\tBPF_STMT(BPF_MISC | BPF_TAX, 0),\n+\n+\t/*\n+\t * Accept empty data frames, we use those for\n+\t * polling activity.\n+\t */\n+\tBPF_STMT(BPF_LD  | BPF_W | BPF_LEN, 0),\n+\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0),\n+\n+\t/*\n+\t * Accept EAPOL frames\n+\t */\n+\tBPF_STMT(BPF_LD  | BPF_W | BPF_IND, 0),\n+\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL),\n+\tBPF_STMT(BPF_LD  | BPF_W | BPF_IND, 4),\n+\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL),\n+\n+\t/* keep these last two statements or change the code below */\n+\t/* return 0 == \"DROP\" */\n+\tBPF_STMT(BPF_RET | BPF_K, 0),\n+\t/* return ~0 == \"keep all\" */\n+\tBPF_STMT(BPF_RET | BPF_K, ~0),\n+};\n+\n+static struct sock_fprog msock_filter = {\n+\t.len = sizeof(msock_filter_insns)/sizeof(msock_filter_insns[0]),\n+\t.filter = msock_filter_insns,\n+};\n+\n+\n+static int add_monitor_filter(int s)\n+{\n+\tint idx;\n+\n+\t/* rewrite all PASS/FAIL jump offsets */\n+\tfor (idx = 0; idx < msock_filter.len; idx++) {\n+\t\tstruct sock_filter *insn = &msock_filter_insns[idx];\n+\n+\t\tif (BPF_CLASS(insn->code) == BPF_JMP) {\n+\t\t\tif (insn->code == (BPF_JMP|BPF_JA)) {\n+\t\t\t\tif (insn->k == PASS)\n+\t\t\t\t\tinsn->k = msock_filter.len - idx - 2;\n+\t\t\t\telse if (insn->k == FAIL)\n+\t\t\t\t\tinsn->k = msock_filter.len - idx - 3;\n+\t\t\t}\n+\n+\t\t\tif (insn->jt == PASS)\n+\t\t\t\tinsn->jt = msock_filter.len - idx - 2;\n+\t\t\telse if (insn->jt == FAIL)\n+\t\t\t\tinsn->jt = msock_filter.len - idx - 3;\n+\n+\t\t\tif (insn->jf == PASS)\n+\t\t\t\tinsn->jf = msock_filter.len - idx - 2;\n+\t\t\telse if (insn->jf == FAIL)\n+\t\t\t\tinsn->jf = msock_filter.len - idx - 3;\n+\t\t}\n+\t}\n+\n+\tif (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER,\n+\t\t       &msock_filter, sizeof(msock_filter))) {\n+\t\tperror(\"SO_ATTACH_FILTER\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static void capwap_remove_monitor_interface(\n+\tstruct wpa_driver_capwap_data *drv)\n+{\n+\treturn;\n+\tdrv->monitor_refcount--;\n+\tif (drv->monitor_refcount > 0)\n+\t\treturn;\n+\n+\tif (drv->monitor_ifidx >= 0) {\n+\t\tcapwap_remove_iface(drv, drv->monitor_ifidx);\n+\t\tdrv->monitor_ifidx = -1;\n+\t}\n+\tif (drv->monitor_sock >= 0) {\n+\t\teloop_unregister_read_sock(drv->monitor_sock);\n+\t\tclose(drv->monitor_sock);\n+\t\tdrv->monitor_sock = -1;\n+\t}\n+}\n+\n+\n+static int\n+capwap_create_monitor_interface(struct wpa_driver_capwap_data *drv)\n+{\n+\twpa_printf(MSG_DEBUG, \"8.5   capwap_create_monitor_interface\\n\");\n+\tchar buf[IFNAMSIZ];\n+\tstruct sockaddr_ll ll;\n+\tint optval;\n+\tsocklen_t optlen;\n+\n+\tif (drv->monitor_ifidx >= 0) {\n+\t\tdrv->monitor_refcount++;\n+\t\treturn 0;\n+\t}\n+\n+\tif (os_strncmp(drv->first_bss.ifname, \"p2p-\", 4) == 0) {\n+\t\t/*\n+\t\t * P2P interface name is of the format p2p-%s-%d. For monitor\n+\t\t * interface name corresponding to P2P GO, replace \"p2p-\" with\n+\t\t * \"mon-\" to retain the same interface name length and to\n+\t\t * indicate that it is a monitor interface.\n+\t\t */\n+\t\tsnprintf(buf, IFNAMSIZ, \"mon-%s\", drv->first_bss.ifname + 4);\n+\t} else {\n+\t\t/* Non-P2P interface with AP functionality. */\n+\t\tsnprintf(buf, IFNAMSIZ, \"mon.%s\", drv->first_bss.ifname);\n+\t}\n+\n+\tbuf[IFNAMSIZ - 1] = '\\0';\n+\n+\tdrv->monitor_ifidx =\n+\t\tcapwap_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,\n+\t\t\t\t     0);\n+\n+\tif (drv->monitor_ifidx == -EOPNOTSUPP) {\n+\t\t/*\n+\t\t * This is backward compatibility for a few versions of\n+\t\t * the kernel only that didn't advertise the right\n+\t\t * attributes for the only driver that then supported\n+\t\t * AP mode w/o monitor -- ath6kl.\n+\t\t */\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Driver does not support \"\n+\t\t\t   \"monitor interface type - try to run without it\");\n+\t\tdrv->device_ap_sme = 1;\n+\t}\n+\n+\tif (drv->monitor_ifidx < 0)\n+\t\treturn -1;\n+\n+\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock, buf, 1))\n+\t\tgoto error;\n+\n+\tmemset(&ll, 0, sizeof(ll));\n+\tll.sll_family = AF_PACKET;\n+\tll.sll_ifindex = drv->monitor_ifidx;\n+\tdrv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n+\tif (drv->monitor_sock < 0) {\n+\t\tperror(\"socket[PF_PACKET,SOCK_RAW]\");\n+\t\tgoto error;\n+\t}\n+\n+\tif (add_monitor_filter(drv->monitor_sock)) {\n+\t\twpa_printf(MSG_INFO, \"Failed to set socket filter for monitor \"\n+\t\t\t   \"interface; do filtering in user space\");\n+\t\t/* This works, but will cost in performance. */\n+\t}\n+\n+\tif (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {\n+\t\tperror(\"monitor socket bind\");\n+\t\tgoto error;\n+\t}\n+\n+\toptlen = sizeof(optval);\n+\toptval = 20;\n+\tif (setsockopt\n+\t    (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {\n+\t\tperror(\"Failed to set socket priority\");\n+\t\tgoto error;\n+\t}\n+\n+\tif (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,\n+\t\t\t\t     drv, NULL)) {\n+\t\twpa_printf(MSG_DEBUG, \"Could not register monitor read socket\\n\");\n+\t\tgoto error;\n+\t}\n+\n+\treturn 0;\n+ error:\n+\tcapwap_remove_monitor_interface(drv);\n+\treturn -1;\n+}\n+\n+\n+static int capwap_setup_ap(struct i802_bss *bss)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Setup AP - device_ap_sme=%d \"\n+\t\t   \"use_monitor=%d\", drv->device_ap_sme, drv->use_monitor);\n+\n+\t/*\n+\t * Disable Probe Request reporting unless we need it in this way for\n+\t * devices that include the AP SME, in the other case (unless using\n+\t * monitor iface) we'll get it through the nl_mgmt socket instead.\n+\t */\n+\tif (!drv->device_ap_sme)\n+\t\twpa_driver_capwap_probe_req_report(bss, 0);\n+\n+\tif (!drv->device_ap_sme && !drv->use_monitor)\n+\t\tif (capwap_mgmt_subscribe_ap(bss))\n+\t\t\treturn -1;\n+\n+\tif (drv->device_ap_sme && !drv->use_monitor)\n+\t\tif (capwap_mgmt_subscribe_ap_dev_sme(bss))\n+\t\t\treturn -1;\n+\n+\tif (!drv->device_ap_sme && drv->use_monitor &&\n+\t    capwap_create_monitor_interface(drv) &&\n+\t    !drv->device_ap_sme)\n+\t\treturn -1;\n+\n+\tif (drv->device_ap_sme &&\n+\t    wpa_driver_capwap_probe_req_report(bss, 1) < 0) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to enable \"\n+\t\t\t   \"Probe Request frame reporting in AP mode\");\n+\t\t/* Try to survive without this */\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static void capwap_teardown_ap(struct i802_bss *bss)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\tif (drv->device_ap_sme) {\n+\t\twpa_driver_capwap_probe_req_report(bss, 0);\n+\t\tif (!drv->use_monitor)\n+\t\t\tcapwap_mgmt_unsubscribe(bss, \"AP teardown (dev SME)\");\n+\t} else if (drv->use_monitor)\n+\t\tcapwap_remove_monitor_interface(drv);\n+\telse\n+\t\tcapwap_mgmt_unsubscribe(bss, \"AP teardown\");\n+\n+\tbss->beacon_set = 0;\n+}\n+\n+\n+static int capwap_send_eapol_data(struct i802_bss *bss,\n+\t\t\t\t   const u8 *addr, const u8 *data,\n+\t\t\t\t   size_t data_len)\n+{\n+\twpa_printf(MSG_DEBUG, \"capwap_send_eapol_data\\n\");\n+\tstruct sockaddr_ll ll;\n+\tint ret;\n+\n+\tif (bss->drv->eapol_tx_sock < 0) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: No socket to send EAPOL\");\n+\t\treturn -1;\n+\t}\n+\n+\tos_memset(&ll, 0, sizeof(ll));\n+\tll.sll_family = AF_PACKET;\n+\tll.sll_ifindex = bss->ifindex;\n+\tll.sll_protocol = htons(ETH_P_PAE);\n+\tll.sll_halen = ETH_ALEN;\n+\tos_memcpy(ll.sll_addr, addr, ETH_ALEN);\n+\tret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,\n+\t\t     (struct sockaddr *) &ll, sizeof(ll));\n+\tif (ret < 0)\n+\t\twpa_printf(MSG_ERROR, \"capwap: EAPOL TX: %s\",\n+\t\t\t   strerror(errno));\n+\n+\treturn ret;\n+}\n+\n+\n+static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n+\n+static int wpa_driver_capwap_hapd_send_eapol(\n+\tvoid *priv, const u8 *addr, const u8 *data,\n+\tsize_t data_len, int encrypt, const u8 *own_addr, u32 flags)\n+{\n+        wpa_printf(MSG_DEBUG, \"-------------- wpa_driver_capwap_hapd_send_eapol\\n\");\n+        return;\n+\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct ieee80211_hdr *hdr;\n+\tsize_t len;\n+\tu8 *pos;\n+\tint res;\n+\tint qos = flags & WPA_STA_WMM;\n+\n+\tif (drv->device_ap_sme || !drv->use_monitor)\n+\t\treturn capwap_send_eapol_data(bss, addr, data, data_len);\n+\n+\tlen = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +\n+\t\tdata_len;\n+\thdr = os_zalloc(len);\n+\tif (hdr == NULL) {\n+\t\twpa_printf(MSG_DEBUG, \"malloc() failed for i802_send_data(len=%lu)\\n\",\n+                       (unsigned long) len);\n+\t\treturn -1;\n+\t}\n+\n+\thdr->frame_control =\n+\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);\n+\thdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);\n+\tif (encrypt)\n+\t\thdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);\n+\tif (qos) {\n+\t\thdr->frame_control |=\n+\t\t\thost_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);\n+\t}\n+\n+\tmemcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);\n+\tmemcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);\n+\tmemcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);\n+\tpos = (u8 *) (hdr + 1);\n+\n+\tif (qos) {\n+\t\t/* Set highest priority in QoS header */\n+\t\tpos[0] = 7;\n+\t\tpos[1] = 0;\n+\t\tpos += 2;\n+\t}\n+\n+\tmemcpy(pos, rfc1042_header, sizeof(rfc1042_header));\n+\tpos += sizeof(rfc1042_header);\n+\tWPA_PUT_BE16(pos, ETH_P_PAE);\n+\tpos += 2;\n+\tmemcpy(pos, data, data_len);\n+\n+\tres = wpa_driver_capwap_send_frame(bss, (u8 *) hdr, len, encrypt, 0,\n+\t\t\t\t\t    0, 0, 0, 0);\n+\tif (res < 0) {\n+\t\twpa_printf(MSG_ERROR, \"i802_send_eapol - packet len: %lu - \"\n+\t\t\t   \"failed: %d (%s)\",\n+\t\t\t   (unsigned long) len, errno, strerror(errno));\n+\t}\n+\tos_free(hdr);\n+\n+\treturn res;\n+}\n+\n+\n+static int wpa_driver_capwap_sta_set_flags(void *priv, const u8 *addr,\n+\t\t\t\t\t    int total_flags,\n+\t\t\t\t\t    int flags_or, int flags_and)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg, *flags = NULL;\n+\tstruct nl80211_sta_flag_update upd;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tflags = nlmsg_alloc();\n+\tif (!flags) {\n+\t\tnlmsg_free(msg);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n+\t\t    if_nametoindex(bss->ifname));\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\n+\t/*\n+\t * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This\n+\t * can be removed eventually.\n+\t */\n+\tif (total_flags & WPA_STA_AUTHORIZED)\n+\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);\n+\n+\tif (total_flags & WPA_STA_WMM)\n+\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);\n+\n+\tif (total_flags & WPA_STA_SHORT_PREAMBLE)\n+\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);\n+\n+\tif (total_flags & WPA_STA_MFP)\n+\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);\n+\n+\tif (total_flags & WPA_STA_TDLS_PEER)\n+\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);\n+\n+\tif (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))\n+\t\tgoto nla_put_failure;\n+\n+\tos_memset(&upd, 0, sizeof(upd));\n+\tupd.mask = sta_flags_capwap(flags_or | ~flags_and);\n+\tupd.set = sta_flags_capwap(flags_or);\n+\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n+\n+\tnlmsg_free(flags);\n+\n+\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\tnlmsg_free(flags);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int wpa_driver_capwap_ap(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t struct wpa_driver_associate_params *params)\n+{\n+\tenum nl80211_iftype nlmode, old_mode;\n+\tstruct hostapd_freq_params freq = {\n+\t\t.freq = params->freq,\n+\t};\n+\n+\tif (params->p2p) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Setup AP operations for P2P \"\n+\t\t\t   \"group (GO)\");\n+\t\tnlmode = NL80211_IFTYPE_P2P_GO;\n+\t} else\n+\t\tnlmode = NL80211_IFTYPE_AP;\n+\n+\told_mode = drv->nlmode;\n+\tif (wpa_driver_capwap_set_mode(&drv->first_bss, nlmode)) {\n+\t\tcapwap_remove_monitor_interface(drv);\n+\t\treturn -1;\n+\t}\n+\n+\tif (wpa_driver_capwap_set_freq(&drv->first_bss, &freq)) {\n+\t\tif (old_mode != nlmode)\n+\t\t\twpa_driver_capwap_set_mode(&drv->first_bss, old_mode);\n+\t\tcapwap_remove_monitor_interface(drv);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static int capwap_leave_ibss(struct wpa_driver_capwap_data *drv)\n+{\n+\tstruct nl_msg *msg;\n+\tint ret = -1;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Leave IBSS failed: ret=%d \"\n+\t\t\t   \"(%s)\", ret, strerror(-ret));\n+\t\tgoto nla_put_failure;\n+\t}\n+\n+\tret = 0;\n+\twpa_printf(MSG_DEBUG, \"capwap: Leave IBSS request sent successfully\");\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_ibss(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t   struct wpa_driver_associate_params *params)\n+{\n+\tstruct nl_msg *msg;\n+\tint ret = -1, i;\n+\tint count = 0;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS (ifindex=%d)\", drv->ifindex);\n+\n+\tif (wpa_driver_capwap_set_mode(&drv->first_bss,\n+\t\t\t\t\tNL80211_IFTYPE_ADHOC)) {\n+\t\twpa_printf(MSG_INFO, \"capwap: Failed to set interface into \"\n+\t\t\t   \"IBSS mode\");\n+\t\treturn -1;\n+\t}\n+\n+retry:\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\n+\tif (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))\n+\t\tgoto nla_put_failure;\n+\n+\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n+\t\t\t  params->ssid, params->ssid_len);\n+\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n+\t\tparams->ssid);\n+\tos_memcpy(drv->ssid, params->ssid, params->ssid_len);\n+\tdrv->ssid_len = params->ssid_len;\n+\n+\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n+\n+//\tif (params->fixed_freq) {\n+//\t\twpa_printf(MSG_DEBUG, \"  * fixed_freq\");\n+//\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_FREQ_FIXED);\n+//\t}\n+\n+//\tif (params->beacon_interval > 0) {\n+//\t\twpa_printf(MSG_DEBUG, \"  * beacon_interval=%d\",\n+//\t\t\t   params->beacon_interval);\n+//\t\tNLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL,\n+//\t\t\t    params->beacon_interval);\n+//\t}\n+\n+//\tif (params->rates[0] > 0) {\n+//\t\twpa_printf(MSG_DEBUG, \"  * basic_rates:\");\n+//\t\ti = 0;\n+//\t\twhile (i < NL80211_MAX_SUPP_RATES &&\n+//\t\t       params->rates[i] > 0) {\n+//\t\t\twpa_printf(MSG_DEBUG, \"    %.1f\",\n+//\t\t\t\t   (double)params->rates[i] / 2);\n+//\t\t\ti++;\n+//\t\t}\n+//\t\tNLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, i,\n+//\t\t\tparams->rates);\n+//\t}\n+\n+//\tif (params->mcast_rate > 0) {\n+//\t\twpa_printf(MSG_DEBUG, \"  * mcast_rates=%.1f\",\n+//\t\t\t   (double)params->mcast_rate / 10);\n+//\t\tNLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate);\n+//\t}\n+\n+//\tif (params->ht_set) {\n+//\t\tswitch(params->htmode) {\n+//\t\t\tcase NL80211_CHAN_HT20:\n+//\t\t\t\twpa_printf(MSG_DEBUG, \"  * ht=HT20\");\n+//\t\t\t\tbreak;\n+//\t\t\tcase NL80211_CHAN_HT40PLUS:\n+//\t\t\t\twpa_printf(MSG_DEBUG, \"  * ht=HT40+\");\n+//\t\t\t\tbreak;\n+//\t\t\tcase NL80211_CHAN_HT40MINUS:\n+//\t\t\t\twpa_printf(MSG_DEBUG, \"  * ht=HT40-\");\n+//\t\t\t\tbreak;\n+//\t\t}\n+//\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,\n+//\t\t\t    params->htmode);\n+//\t}\n+\n+\tret = capwap_set_conn_keys(params, msg);\n+\tif (ret)\n+\t\tgoto nla_put_failure;\n+\n+\tif (params->bssid && params->fixed_bssid) {\n+\t\twpa_printf(MSG_DEBUG, \"  * BSSID=\" MACSTR,\n+\t\t\t   MAC2STR(params->bssid));\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n+\t}\n+\n+\tif (params->key_mgmt_suite == KEY_MGMT_802_1X ||\n+\t    params->key_mgmt_suite == KEY_MGMT_PSK ||\n+\t    params->key_mgmt_suite == KEY_MGMT_802_1X_SHA256 ||\n+\t    params->key_mgmt_suite == KEY_MGMT_PSK_SHA256) {\n+\t\twpa_printf(MSG_DEBUG, \"  * control port\");\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);\n+\t}\n+\n+\tif (params->wpa_ie) {\n+\t\twpa_hexdump(MSG_DEBUG,\n+\t\t\t    \"  * Extra IEs for Beacon/Probe Response frames\",\n+\t\t\t    params->wpa_ie, params->wpa_ie_len);\n+\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n+\t\t\tparams->wpa_ie);\n+\t}\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS failed: ret=%d (%s)\",\n+\t\t\t   ret, strerror(-ret));\n+\t\tcount++;\n+\t\tif (ret == -EALREADY && count == 1) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Retry IBSS join after \"\n+\t\t\t\t   \"forced leave\");\n+\t\t\tcapwap_leave_ibss(drv);\n+\t\t\tnlmsg_free(msg);\n+\t\t\tgoto retry;\n+\t\t}\n+\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS request sent successfully\");\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_try_connect(\n+\tstruct wpa_driver_capwap_data *drv,\n+\tstruct wpa_driver_associate_params *params)\n+{\n+\tstruct nl_msg *msg;\n+\tenum nl80211_auth_type type;\n+\tint ret = 0;\n+\tint algs;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Connect (ifindex=%d)\", drv->ifindex);\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_CONNECT);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tif (params->bssid) {\n+\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n+\t\t\t   MAC2STR(params->bssid));\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n+\t}\n+\tif (params->freq) {\n+\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n+\t}\n+\tif (params->bg_scan_period >= 0) {\n+\t\twpa_printf(MSG_DEBUG, \"  * bg scan period=%d\",\n+\t\t\t   params->bg_scan_period);\n+\t\tNLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,\n+\t\t\t    params->bg_scan_period);\n+\t}\n+\tif (params->ssid) {\n+\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n+\t\t\t\t  params->ssid, params->ssid_len);\n+\t\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n+\t\t\tparams->ssid);\n+\t\tif (params->ssid_len > sizeof(drv->ssid))\n+\t\t\tgoto nla_put_failure;\n+\t\tos_memcpy(drv->ssid, params->ssid, params->ssid_len);\n+\t\tdrv->ssid_len = params->ssid_len;\n+\t}\n+\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->wpa_ie, params->wpa_ie_len);\n+\tif (params->wpa_ie)\n+\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n+\t\t\tparams->wpa_ie);\n+\n+\talgs = 0;\n+\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n+\t\talgs++;\n+\tif (params->auth_alg & WPA_AUTH_ALG_SHARED)\n+\t\talgs++;\n+\tif (params->auth_alg & WPA_AUTH_ALG_LEAP)\n+\t\talgs++;\n+\tif (algs > 1) {\n+\t\twpa_printf(MSG_DEBUG, \"  * Leave out Auth Type for automatic \"\n+\t\t\t   \"selection\");\n+\t\tgoto skip_auth_type;\n+\t}\n+\n+\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n+\t\ttype = NL80211_AUTHTYPE_OPEN_SYSTEM;\n+\telse if (params->auth_alg & WPA_AUTH_ALG_SHARED)\n+\t\ttype = NL80211_AUTHTYPE_SHARED_KEY;\n+\telse if (params->auth_alg & WPA_AUTH_ALG_LEAP)\n+\t\ttype = NL80211_AUTHTYPE_NETWORK_EAP;\n+\telse if (params->auth_alg & WPA_AUTH_ALG_FT)\n+\t\ttype = NL80211_AUTHTYPE_FT;\n+\telse\n+\t\tgoto nla_put_failure;\n+\n+\twpa_printf(MSG_DEBUG, \"  * Auth Type %d\", type);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);\n+\n+skip_auth_type:\n+\tif (params->wpa_proto) {\n+\t\tenum nl80211_wpa_versions ver = 0;\n+\n+\t\tif (params->wpa_proto & WPA_PROTO_WPA)\n+\t\t\tver |= NL80211_WPA_VERSION_1;\n+\t\tif (params->wpa_proto & WPA_PROTO_RSN)\n+\t\t\tver |= NL80211_WPA_VERSION_2;\n+\n+\t\twpa_printf(MSG_DEBUG, \"  * WPA Versions 0x%x\", ver);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);\n+\t}\n+\n+\tif (params->pairwise_suite != CIPHER_NONE) {\n+\t\tint cipher;\n+\n+\t\tswitch (params->pairwise_suite) {\n+\t\tcase CIPHER_SMS4:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_SMS4;\n+\t\t\tbreak;\n+\t\tcase CIPHER_WEP40:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n+\t\t\tbreak;\n+\t\tcase CIPHER_WEP104:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n+\t\t\tbreak;\n+\t\tcase CIPHER_CCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_GCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_GCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_TKIP:\n+\t\tdefault:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n+\t\t\tbreak;\n+\t\t}\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);\n+\t}\n+\n+\tif (params->group_suite != CIPHER_NONE) {\n+\t\tint cipher;\n+\n+\t\tswitch (params->group_suite) {\n+\t\tcase CIPHER_SMS4:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_SMS4;\n+\t\t\tbreak;\n+\t\tcase CIPHER_WEP40:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n+\t\t\tbreak;\n+\t\tcase CIPHER_WEP104:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n+\t\t\tbreak;\n+\t\tcase CIPHER_CCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_GCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_GCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_TKIP:\n+\t\tdefault:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n+\t\t\tbreak;\n+\t\t}\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);\n+\t}\n+\n+\tif (params->key_mgmt_suite == KEY_MGMT_802_1X ||\n+\t    params->key_mgmt_suite == KEY_MGMT_PSK ||\n+\t    params->key_mgmt_suite == KEY_MGMT_CCKM) {\n+\t\tint mgmt = WLAN_AKM_SUITE_PSK;\n+\n+\t\tswitch (params->key_mgmt_suite) {\n+\t\tcase KEY_MGMT_CCKM:\n+\t\t\tmgmt = WLAN_AKM_SUITE_CCKM;\n+\t\t\tbreak;\n+\t\tcase KEY_MGMT_802_1X:\n+\t\t\tmgmt = WLAN_AKM_SUITE_8021X;\n+\t\t\tbreak;\n+\t\tcase KEY_MGMT_PSK:\n+\t\tdefault:\n+\t\t\tmgmt = WLAN_AKM_SUITE_PSK;\n+\t\t\tbreak;\n+\t\t}\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);\n+\t}\n+\n+#ifdef CONFIG_IEEE80211W\n+\tif (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);\n+#endif /* CONFIG_IEEE80211W */\n+\n+\tif (params->disable_ht)\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);\n+\n+\tif (params->htcaps && params->htcaps_mask) {\n+\t\tint sz = sizeof(struct ieee80211_ht_capabilities);\n+\t\tNLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);\n+\t\tNLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,\n+\t\t\tparams->htcaps_mask);\n+\t}\n+\n+\tret = capwap_set_conn_keys(params, msg);\n+\tif (ret)\n+\t\tgoto nla_put_failure;\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: MLME connect failed: ret=%d \"\n+\t\t\t   \"(%s)\", ret, strerror(-ret));\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+\twpa_printf(MSG_DEBUG, \"capwap: Connect request send successfully\");\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+\n+}\n+\n+\n+static int wpa_driver_capwap_connect(\n+\tstruct wpa_driver_capwap_data *drv,\n+\tstruct wpa_driver_associate_params *params)\n+{\n+\tint ret = wpa_driver_capwap_try_connect(drv, params);\n+\tif (ret == -EALREADY) {\n+\t\t/*\n+\t\t * cfg80211 does not currently accept new connections if\n+\t\t * we are already connected. As a workaround, force\n+\t\t * disconnection and try again.\n+\t\t */\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Explicitly \"\n+\t\t\t   \"disconnecting before reassociation \"\n+\t\t\t   \"attempt\");\n+\t\tif (wpa_driver_capwap_disconnect(\n+\t\t\t    drv, WLAN_REASON_PREV_AUTH_NOT_VALID))\n+\t\t\treturn -1;\n+\t\t/* Ignore the next local disconnect message. */\n+\t\tdrv->ignore_next_local_disconnect = 1;\n+\t\tret = wpa_driver_capwap_try_connect(drv, params);\n+\t}\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_associate(\n+\tvoid *priv, struct wpa_driver_associate_params *params)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret = -1;\n+\tstruct nl_msg *msg;\n+\n+\tif (params->mode == IEEE80211_MODE_AP)\n+\t\treturn wpa_driver_capwap_ap(drv, params);\n+\n+\tif (params->mode == IEEE80211_MODE_IBSS)\n+\t\treturn wpa_driver_capwap_ibss(drv, params);\n+\n+\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {\n+\t\tenum nl80211_iftype nlmode = params->p2p ?\n+\t\t\tNL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;\n+\n+\t\tif (wpa_driver_capwap_set_mode(priv, nlmode) < 0)\n+\t\t\treturn -1;\n+\t\treturn wpa_driver_capwap_connect(drv, params);\n+\t}\n+\n+\tdrv->associated = 0;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Associate (ifindex=%d)\",\n+\t\t   drv->ifindex);\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tif (params->bssid) {\n+\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n+\t\t\t   MAC2STR(params->bssid));\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n+\t}\n+\tif (params->freq) {\n+\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n+\t\tdrv->assoc_freq = params->freq;\n+\t} else\n+\t\tdrv->assoc_freq = 0;\n+\tif (params->bg_scan_period >= 0) {\n+\t\twpa_printf(MSG_DEBUG, \"  * bg scan period=%d\",\n+\t\t\t   params->bg_scan_period);\n+\t\tNLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,\n+\t\t\t    params->bg_scan_period);\n+\t}\n+\tif (params->ssid) {\n+\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n+\t\t\t\t  params->ssid, params->ssid_len);\n+\t\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n+\t\t\tparams->ssid);\n+\t\tif (params->ssid_len > sizeof(drv->ssid))\n+\t\t\tgoto nla_put_failure;\n+\t\tos_memcpy(drv->ssid, params->ssid, params->ssid_len);\n+\t\tdrv->ssid_len = params->ssid_len;\n+\t}\n+\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->wpa_ie, params->wpa_ie_len);\n+\tif (params->wpa_ie)\n+\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n+\t\t\tparams->wpa_ie);\n+\n+\tif (params->pairwise_suite != CIPHER_NONE) {\n+\t\tint cipher;\n+\n+\t\tswitch (params->pairwise_suite) {\n+\t\tcase CIPHER_WEP40:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n+\t\t\tbreak;\n+\t\tcase CIPHER_WEP104:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n+\t\t\tbreak;\n+\t\tcase CIPHER_CCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_GCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_GCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_TKIP:\n+\t\tdefault:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n+\t\t\tbreak;\n+\t\t}\n+\t\twpa_printf(MSG_DEBUG, \"  * pairwise=0x%x\", cipher);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);\n+\t}\n+\n+\tif (params->group_suite != CIPHER_NONE) {\n+\t\tint cipher;\n+\n+\t\tswitch (params->group_suite) {\n+\t\tcase CIPHER_WEP40:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n+\t\t\tbreak;\n+\t\tcase CIPHER_WEP104:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n+\t\t\tbreak;\n+\t\tcase CIPHER_CCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_GCMP:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_GCMP;\n+\t\t\tbreak;\n+\t\tcase CIPHER_TKIP:\n+\t\tdefault:\n+\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n+\t\t\tbreak;\n+\t\t}\n+\t\twpa_printf(MSG_DEBUG, \"  * group=0x%x\", cipher);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);\n+\t}\n+\n+#ifdef CONFIG_IEEE80211W\n+\tif (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);\n+#endif /* CONFIG_IEEE80211W */\n+\n+\tNLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);\n+\n+\tif (params->prev_bssid) {\n+\t\twpa_printf(MSG_DEBUG, \"  * prev_bssid=\" MACSTR,\n+\t\t\t   MAC2STR(params->prev_bssid));\n+\t\tNLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,\n+\t\t\tparams->prev_bssid);\n+\t}\n+\n+\tif (params->disable_ht)\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);\n+\n+\tif (params->htcaps && params->htcaps_mask) {\n+\t\tint sz = sizeof(struct ieee80211_ht_capabilities);\n+\t\tNLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);\n+\t\tNLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,\n+\t\t\tparams->htcaps_mask);\n+\t}\n+\n+\tif (params->p2p)\n+\t\twpa_printf(MSG_DEBUG, \"  * P2P group\");\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_dbg(drv->ctx, MSG_DEBUG,\n+\t\t\t\"capwap: MLME command failed (assoc): ret=%d (%s)\",\n+\t\t\tret, strerror(-ret));\n+\t\tcapwap_dump_scan(drv);\n+\t\tgoto nla_put_failure;\n+\t}\n+\tret = 0;\n+\twpa_printf(MSG_DEBUG, \"capwap: Association request send \"\n+\t\t   \"successfully\");\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int capwap_set_mode(struct wpa_driver_capwap_data *drv,\n+\t\t\t    int ifindex, enum nl80211_iftype mode)\n+{\n+\twpa_printf(MSG_DEBUG, \"                                         1.wpa_driver_capwap_set_mode\\n\");\n+\tstruct nl_msg *msg;\n+\tint ret = -ENOBUFS;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Set mode ifindex %d iftype %d (%s)\",\n+\t\t   ifindex, mode, capwap_iftype_str(mode));\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (!ret)\n+\t\treturn 0;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\twpa_printf(MSG_DEBUG, \"capwap: Failed to set interface %d to mode %d:\"\n+\t\t   \" %d (%s)\", ifindex, mode, ret, strerror(-ret));\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_set_mode(struct i802_bss *bss,\n+\t\t\t\t       enum nl80211_iftype nlmode)\n+{\n+\twpa_printf(MSG_DEBUG, \"                                 6.wpa_driver_capwap_set_mode\\n\");\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret = -1;\n+\tint i;\n+\tint was_ap = is_ap_interface(drv->nlmode);\n+\tint res;\n+\n+\tres = capwap_set_mode(drv, drv->ifindex, nlmode);\n+\tif (res == 0) {\n+\t\tdrv->nlmode = nlmode;\n+\t\tret = 0;\n+\t\tgoto done;\n+\t}\n+\n+\tif (res == -ENODEV)\n+\t\treturn -1;\n+\n+\tif (nlmode == drv->nlmode) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Interface already in \"\n+\t\t\t   \"requested mode - ignore error\");\n+\t\tret = 0;\n+\t\tgoto done; /* Already in the requested mode */\n+\t}\n+\n+\t/* mac80211 doesn't allow mode changes while the device is up, so\n+\t * take the device down, try to set the mode again, and bring the\n+\t * device back up.\n+\t */\n+\twpa_printf(MSG_DEBUG, \"capwap: Try mode change after setting \"\n+\t\t   \"interface down\");\n+\tfor (i = 0; i < 10; i++) {\n+\t\tres = linux_set_fake_iface_flags(drv->global->ioctl_sock,\n+\t\t\t\t\t    bss->ifname, 0);\n+\t\tif (res == -EACCES || res == -ENODEV)\n+\t\t\tbreak;\n+\t\tif (res == 0) {\n+\t\t\t/* Try to set the mode again while the interface is\n+\t\t\t * down */\n+\t\t\tret = capwap_set_mode(drv, drv->ifindex, nlmode);\n+\t\t\tif (ret == -EACCES)\n+\t\t\t\tbreak;\n+\t\t\tif (res && !ret)\n+\t\t\t\tret = -1;\n+\t\t\telse if (ret != -EBUSY)\n+\t\t\t\tbreak;\n+\t\t} else\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to set \"\n+\t\t\t\t   \"interface down\");\n+\t\tos_sleep(0, 100000);\n+\t}\n+\n+\tif (!ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Mode change succeeded while \"\n+\t\t\t   \"interface is down\");\n+\t\tdrv->nlmode = nlmode;\n+\t\tdrv->ignore_if_down_event = 1;\n+\t\tlinux_set_fake_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);\n+\t}\n+\n+done:\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Interface mode change to %d \"\n+\t\t\t   \"from %d failed\", nlmode, drv->nlmode);\n+\t\treturn ret;\n+\t}\n+\n+\tif (is_p2p_interface(nlmode))\n+\t\tcapwap_disable_11b_rates(drv, drv->ifindex, 1);\n+\telse if (drv->disabled_11b_rates)\n+\t\tcapwap_disable_11b_rates(drv, drv->ifindex, 0);\n+\n+\tif (is_ap_interface(nlmode)) {\n+\t\tcapwap_mgmt_unsubscribe(bss, \"start AP\");\n+\t\t/* Setup additional AP mode functionality if needed */\n+\t\tif (capwap_setup_ap(bss))\n+\t\t\treturn -1;\n+\t} else if (was_ap) {\n+\t\t/* Remove additional AP mode functionality */\n+\t\tcapwap_teardown_ap(bss);\n+\t} else {\n+\t\tcapwap_mgmt_unsubscribe(bss, \"mode change\");\n+\t}\n+\n+\tif (!bss->in_deinit && !is_ap_interface(nlmode) &&\n+\t    capwap_mgmt_subscribe_non_ap(bss) < 0)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to register Action \"\n+\t\t\t   \"frame processing - ignore for now\");\n+\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_get_capa(void *priv,\n+\t\t\t\t       struct wpa_driver_capa *capa)\n+{\n+\twpa_printf(MSG_DEBUG, \"                         1.wpa_driver_capwap_get_capa\\n\");\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tif (!drv->has_capability)\n+\t\treturn -1;\n+\tos_memcpy(capa, &drv->capa, sizeof(*capa));\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_set_operstate(void *priv, int state)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\twpa_printf(MSG_DEBUG, \"%s: operstate %d->%d (%s)\",\n+\t\t   __func__, drv->operstate, state, state ? \"UP\" : \"DORMANT\");\n+\tdrv->operstate = state;\n+\treturn netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,\n+\t\t\t\t      state ? IF_OPER_UP : IF_OPER_DORMANT);\n+}\n+\n+\n+static int wpa_driver_capwap_set_supp_port(void *priv, int authorized)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tstruct nl80211_sta_flag_update upd;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n+\t\t    if_nametoindex(bss->ifname));\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);\n+\n+\tos_memset(&upd, 0, sizeof(upd));\n+\tupd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);\n+\tif (authorized)\n+\t\tupd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);\n+\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n+\n+\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+/* Set kernel driver on given frequency (MHz) */\n+static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)\n+{\n+\twpa_printf(MSG_DEBUG, \"                                 1.i802_set_freq \\n\");\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_set_freq(bss, freq);\n+}\n+\n+\n+#if defined(HOSTAPD) || defined(CONFIG_AP)\n+\n+static inline int min_int(int a, int b)\n+{\n+\tif (a < b)\n+\t\treturn a;\n+\treturn b;\n+}\n+\n+\n+static int get_key_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\t/*\n+\t * TODO: validate the key index and mac address!\n+\t * Otherwise, there's a race condition as soon as\n+\t * the kernel starts sending key notifications.\n+\t */\n+\n+\tif (tb[NL80211_ATTR_KEY_SEQ])\n+\t\tmemcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),\n+\t\t       min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,\n+\t\t\t   int idx, u8 *seq)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);\n+\n+\tif (addr)\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));\n+\n+\tmemset(seq, 0, 6);\n+\n+\treturn send_and_recv_msgs(drv, msg, get_key_handler, seq);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int i802_set_rts(void *priv, int rts)\n+{\n+\twpa_printf(MSG_DEBUG, \"> i802_set_rts %d \\n\",rts);\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret = -ENOBUFS;\n+\tu32 val;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tif (rts >= 2347)\n+\t\tval = (u32) -1;\n+\telse\n+\t\tval = rts;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (!ret)\n+\t\treturn 0;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\twpa_printf(MSG_DEBUG, \"capwap: Failed to set RTS threshold %d: \"\n+\t\t   \"%d (%s)\", rts, ret, strerror(-ret));\n+\treturn ret;\n+}\n+\n+\n+static int i802_set_frag(void *priv, int frag)\n+{\n+\twpa_printf(MSG_DEBUG, \"> i802_set_frag  %d\\n\",frag);\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret = -ENOBUFS;\n+\tu32 val;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tif (frag >= 2346)\n+\t\tval = (u32) -1;\n+\telse\n+\t\tval = frag;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (!ret)\n+\t\treturn 0;\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\twpa_printf(MSG_DEBUG, \"capwap: Failed to set fragmentation threshold \"\n+\t\t   \"%d: %d (%s)\", frag, ret, strerror(-ret));\n+\treturn ret;\n+}\n+\n+\n+static int i802_flush(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint res;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);\n+\n+\t/*\n+\t * XXX: FIX! this needs to flush all VLANs too\n+\t */\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n+\t\t    if_nametoindex(bss->ifname));\n+\n+\tres = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tif (res) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Station flush failed: ret=%d \"\n+\t\t\t   \"(%s)\", res, strerror(-res));\n+\t}\n+\treturn res;\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+#endif /* HOSTAPD || CONFIG_AP */\n+\n+\n+static int get_sta_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tstruct hostap_sta_driver_data *data = arg;\n+\tstruct nlattr *stats[NL80211_STA_INFO_MAX + 1];\n+\tstatic struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {\n+\t\t[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },\n+\t\t[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },\n+\t\t[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },\n+\t\t[NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },\n+\t\t[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },\n+\t\t[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },\n+\t};\n+\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\n+\t/*\n+\t * TODO: validate the interface and mac address!\n+\t * Otherwise, there's a race condition as soon as\n+\t * the kernel starts sending station notifications.\n+\t */\n+\n+\tif (!tb[NL80211_ATTR_STA_INFO]) {\n+\t\twpa_printf(MSG_DEBUG, \"sta stats missing!\");\n+\t\treturn NL_SKIP;\n+\t}\n+\tif (nla_parse_nested(stats, NL80211_STA_INFO_MAX,\n+\t\t\t     tb[NL80211_ATTR_STA_INFO],\n+\t\t\t     stats_policy)) {\n+\t\twpa_printf(MSG_DEBUG, \"failed to parse nested attributes!\");\n+\t\treturn NL_SKIP;\n+\t}\n+\n+\tif (stats[NL80211_STA_INFO_INACTIVE_TIME])\n+\t\tdata->inactive_msec =\n+\t\t\tnla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);\n+\tif (stats[NL80211_STA_INFO_RX_BYTES])\n+\t\tdata->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);\n+\tif (stats[NL80211_STA_INFO_TX_BYTES])\n+\t\tdata->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);\n+\tif (stats[NL80211_STA_INFO_RX_PACKETS])\n+\t\tdata->rx_packets =\n+\t\t\tnla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);\n+\tif (stats[NL80211_STA_INFO_TX_PACKETS])\n+\t\tdata->tx_packets =\n+\t\t\tnla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);\n+\tif (stats[NL80211_STA_INFO_TX_FAILED])\n+\t\tdata->tx_retry_failed =\n+\t\t\tnla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);\n+\n+\treturn NL_SKIP;\n+}\n+\n+static int i802_read_sta_data(struct i802_bss *bss,\n+\t\t\t      struct hostap_sta_driver_data *data,\n+\t\t\t      const u8 *addr)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\n+\tos_memset(data, 0, sizeof(*data));\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);\n+\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n+\n+\treturn send_and_recv_msgs(drv, msg, get_sta_handler, data);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+#if defined(HOSTAPD) || defined(CONFIG_AP)\n+\n+static int i802_set_tx_queue_params(void *priv, int queue, int aifs,\n+\t\t\t\t    int cw_min, int cw_max, int burst_time)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tstruct nlattr *txq, *params;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n+\n+\ttxq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);\n+\tif (!txq)\n+\t\tgoto nla_put_failure;\n+\n+\t/* We are only sending parameters for a single TXQ at a time */\n+\tparams = nla_nest_start(msg, 1);\n+\tif (!params)\n+\t\tgoto nla_put_failure;\n+\n+\tswitch (queue) {\n+\tcase 0:\n+\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO);\n+\t\tbreak;\n+\tcase 1:\n+\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI);\n+\t\tbreak;\n+\tcase 2:\n+\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE);\n+\t\tbreak;\n+\tcase 3:\n+\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK);\n+\t\tbreak;\n+\t}\n+\t/* Burst time is configured in units of 0.1 msec and TXOP parameter in\n+\t * 32 usec, so need to convert the value here. */\n+\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32);\n+\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);\n+\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);\n+\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);\n+\n+\tnla_nest_end(msg, params);\n+\n+\tnla_nest_end(msg, txq);\n+\n+\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n+\t\treturn 0;\n+\tmsg = NULL;\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -1;\n+}\n+\n+\n+static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,\n+\t\t\t     const char *ifname, int vlan_id)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret = -ENOBUFS;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n+\t\t    if_nametoindex(bss->ifname));\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN,\n+\t\t    if_nametoindex(ifname));\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: NL80211_ATTR_STA_VLAN (addr=\"\n+\t\t\t   MACSTR \" ifname=%s vlan_id=%d) failed: %d (%s)\",\n+\t\t\t   MAC2STR(addr), ifname, vlan_id, ret,\n+\t\t\t   strerror(-ret));\n+\t}\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int i802_get_inact_sec(void *priv, const u8 *addr)\n+{\n+\tstruct hostap_sta_driver_data data;\n+\tint ret;\n+\n+\tdata.inactive_msec = (unsigned long) -1;\n+\tret = i802_read_sta_data(priv, &data, addr);\n+\tif (ret || data.inactive_msec == (unsigned long) -1)\n+\t\treturn -1;\n+\treturn data.inactive_msec / 1000;\n+}\n+\n+\n+static int i802_sta_clear_stats(void *priv, const u8 *addr)\n+{\n+#if 0\n+\t/* TODO */\n+#endif\n+\treturn 0;\n+}\n+\n+\n+static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,\n+\t\t\t   int reason)\n+{\n+\twpa_printf(MSG_DEBUG, \"                                                                 1.i802_sta_deauth \\n\");\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct ieee80211_mgmt mgmt;\n+\n+\tif (drv->device_ap_sme)\n+\t\treturn wpa_driver_capwap_sta_remove(bss, addr);\n+\n+\tmemset(&mgmt, 0, sizeof(mgmt));\n+\tmgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,\n+\t\t\t\t\t  WLAN_FC_STYPE_DEAUTH);\n+\tmemcpy(mgmt.da, addr, ETH_ALEN);\n+\tmemcpy(mgmt.sa, own_addr, ETH_ALEN);\n+\tmemcpy(mgmt.bssid, own_addr, ETH_ALEN);\n+\tmgmt.u.deauth.reason_code = host_to_le16(reason);\n+\tint r = wpa_driver_capwap_send_mlme(bss, (u8 *) &mgmt,\n+\t\t\t\t\t    IEEE80211_HDRLEN +\n+\t\t\t\t\t    sizeof(mgmt.u.deauth), 0, 0, 0, 0,\n+\t\t\t\t\t    0);\n+\treturn r;\n+}\n+\n+\n+static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,\n+\t\t\t     int reason)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct ieee80211_mgmt mgmt;\n+\n+\tif (drv->device_ap_sme)\n+\t\treturn wpa_driver_capwap_sta_remove(bss, addr);\n+\n+\tmemset(&mgmt, 0, sizeof(mgmt));\n+\tmgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,\n+\t\t\t\t\t  WLAN_FC_STYPE_DISASSOC);\n+\tmemcpy(mgmt.da, addr, ETH_ALEN);\n+\tmemcpy(mgmt.sa, own_addr, ETH_ALEN);\n+\tmemcpy(mgmt.bssid, own_addr, ETH_ALEN);\n+\tmgmt.u.disassoc.reason_code = host_to_le16(reason);\n+\treturn wpa_driver_capwap_send_mlme(bss, (u8 *) &mgmt,\n+\t\t\t\t\t    IEEE80211_HDRLEN +\n+\t\t\t\t\t    sizeof(mgmt.u.disassoc), 0, 0, 0, 0,\n+\t\t\t\t\t    0);\n+}\n+\n+#endif /* HOSTAPD || CONFIG_AP */\n+\n+#ifdef HOSTAPD\n+\n+static void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n+{\n+\twpa_printf(MSG_DEBUG,\"                                  3.add_ifidx\\n\");\n+\tint i;\n+\tint *old;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Add own interface ifindex %d\",\n+\t\t   ifidx);\n+\tfor (i = 0; i < drv->num_if_indices; i++) {\n+\t\tif (drv->if_indices[i] == 0) {\n+\t\t\tdrv->if_indices[i] = ifidx;\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\tif (drv->if_indices != drv->default_if_indices)\n+\t\told = drv->if_indices;\n+\telse\n+\t\told = NULL;\n+\n+\tdrv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,\n+\t\t\t\t\t   sizeof(int));\n+\tif (!drv->if_indices) {\n+\t\tif (!old)\n+\t\t\tdrv->if_indices = drv->default_if_indices;\n+\t\telse\n+\t\t\tdrv->if_indices = old;\n+\t\twpa_printf(MSG_ERROR, \"Failed to reallocate memory for \"\n+\t\t\t   \"interfaces\");\n+\t\twpa_printf(MSG_ERROR, \"Ignoring EAPOL on interface %d\", ifidx);\n+\t\treturn;\n+\t} else if (!old)\n+\t\tos_memcpy(drv->if_indices, drv->default_if_indices,\n+\t\t\t  sizeof(drv->default_if_indices));\n+\tdrv->if_indices[drv->num_if_indices] = ifidx;\n+\tdrv->num_if_indices++;\n+}\n+\n+\n+static void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < drv->num_if_indices; i++) {\n+\t\tif (drv->if_indices[i] == ifidx) {\n+\t\t\tdrv->if_indices[i] = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+\n+static int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < drv->num_if_indices; i++)\n+\t\tif (drv->if_indices[i] == ifidx)\n+\t\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+\n+static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,\n+                            const char *bridge_ifname)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tchar name[IFNAMSIZ + 1];\n+\n+\tos_snprintf(name, sizeof(name), \"%s.sta%d\", bss->ifname, aid);\n+\twpa_printf(MSG_DEBUG, \"capwap: Set WDS STA addr=\" MACSTR\n+\t\t   \" aid=%d val=%d name=%s\", MAC2STR(addr), aid, val, name);\n+\tif (val) {\n+\t\tif (!if_nametoindex(name)) {\n+\t\t\tif (capwap_create_iface(drv, name,\n+\t\t\t\t\t\t NL80211_IFTYPE_AP_VLAN,\n+\t\t\t\t\t\t bss->addr, 1) < 0)\n+\t\t\t\treturn -1;\n+\t\t\tif (bridge_ifname &&\n+\t\t\t    linux_br_fake_add_if(drv->global->ioctl_sock,\n+\t\t\t\t\t    bridge_ifname, name) < 0)\n+\t\t\t\treturn -1;\n+\t\t}\n+\t\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock, name, 1)) {\n+\t\t\twpa_printf(MSG_ERROR, \"capwap: Failed to set WDS STA \"\n+\t\t\t\t   \"interface %s up\", name);\n+\t\t}\n+\t\treturn i802_set_sta_vlan(priv, addr, name, 0);\n+\t} else {\n+\t\tif (bridge_ifname)\n+\t\t\tlinux_br_fake_del_if(drv->global->ioctl_sock, bridge_ifname,\n+\t\t\t\t\tname);\n+\n+\t\ti802_set_sta_vlan(priv, addr, bss->ifname, 0);\n+\t\treturn wpa_driver_capwap_if_remove(priv, WPA_IF_AP_VLAN,\n+\t\t\t\t\t\t    name);\n+\t}\n+}\n+\n+void AC_handle_eapol(struct wpa_driver_capwap_data *drv, u8 *buf, int len){\n+\tu8 sa[6];\n+\n+\tint hlen = GetEapol_Frame(sa, buf, len);\n+\t//stampa_mac(\"AC eapol: \" ,sa);\n+\n+\tdrv_event_eapol_rx(drv->ctx, sa, buf + hlen, len - hlen);\n+}\n+\n+\n+\n+static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)\n+{\n+\twpa_printf(MSG_DEBUG, \"handle_eapol %d\\n\",sock);\n+\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n+\tstruct sockaddr_ll lladdr;\n+\tunsigned char buf[3000];\n+\tint len;\n+\tsocklen_t fromlen = sizeof(lladdr);\n+\n+\tlen = recvfrom(sock, buf, sizeof(buf), 0,\n+\t\t       (struct sockaddr *)&lladdr, &fromlen);\n+\n+\treturn;\n+\tif (len < 0) {\n+\twpa_printf(MSG_ERROR, \"recv\");\n+               return;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"LOCALE\");\n+\tstampa_frame(buf,len);\n+\n+\twpa_printf(MSG_DEBUG, \"%d,%d\", len,have_ifidx(drv, lladdr.sll_ifindex));\n+\n+\t//stampa_mac(\"  EAPOL MAC: \",lladdr.sll_addr);\n+\tdrv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);\n+}\n+\n+\n+static int i802_check_bridge(struct wpa_driver_capwap_data *drv,\n+\t\t\t     struct i802_bss *bss,\n+\t\t\t     const char *brname, const char *ifname)\n+{\n+\twpa_printf(MSG_DEBUG, \"                                 7.i802_check_bridge\\n\");\n+\tint ifindex;\n+\tchar in_br[IFNAMSIZ];\n+\n+\tos_strlcpy(bss->brname, brname, IFNAMSIZ);\n+\tifindex = if_nametoindex(brname);\n+\tif (ifindex == 0) {\n+\t\t/*\n+\t\t * Bridge was configured, but the bridge device does\n+\t\t * not exist. Try to add it now.\n+\t\t */\n+\t\tif (linux_br_fake_add(drv->global->ioctl_sock, brname) < 0) {\n+\t\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add the \"\n+\t\t\t\t   \"bridge interface %s: %s\",\n+\t\t\t\t   brname, strerror(errno));\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbss->added_bridge = 1;\n+\t\tadd_ifidx(drv, if_nametoindex(brname));\n+\t}\n+\n+\tif (linux_br_fake_get(in_br, ifname) == 0) {\n+\t\tif (os_strcmp(in_br, brname) == 0)\n+\t\t\treturn 0; /* already in the bridge */\n+\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Removing interface %s from \"\n+\t\t\t   \"bridge %s\", ifname, in_br);\n+\t\tif (linux_br_fake_del_if(drv->global->ioctl_sock, in_br, ifname) <\n+\t\t    0) {\n+\t\t\twpa_printf(MSG_ERROR, \"capwap: Failed to \"\n+\t\t\t\t   \"remove interface %s from bridge \"\n+\t\t\t\t   \"%s: %s\",\n+\t\t\t\t   ifname, brname, strerror(errno));\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Adding interface %s into bridge %s\",\n+\t\t   ifname, brname);\n+\tif (linux_br_fake_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add interface %s \"\n+\t\t\t   \"into bridge %s: %s\",\n+\t\t\t   ifname, brname, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\tbss->added_if_into_bridge = 1;\n+\n+\treturn 0;\n+}\n+\n+static void *i802_init(struct hostapd_data *hapd,\n+\t\t       struct wpa_init_params *params)\n+{\n+\twpa_printf(MSG_DEBUG, \"                         1.i802_init\\n\");\n+\tstruct wpa_driver_capwap_data *drv;\n+\tstruct i802_bss *bss;\n+\tsize_t i;\n+\tchar brname[IFNAMSIZ];\n+\tint ifindex, br_ifindex;\n+\tint br_added = 0;\n+\n+\tbss = wpa_driver_capwap_init(hapd, params->ifname,\n+\t\t\t\t      params->global_priv);\n+\tif (bss == NULL)\n+\t\treturn NULL;\n+\n+\tdrv = bss->drv;\n+\tdrv->nlmode = NL80211_IFTYPE_AP;\n+\tdrv->eapol_sock = -1;\n+\n+\tif (linux_br_fake_get(brname, params->ifname) == 0) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Interface %s is in bridge %s\",\n+\t\t\t   params->ifname, brname);\n+\t\tbr_ifindex = if_nametoindex(brname);\n+\t} else {\n+\t\tbrname[0] = '\\0';\n+\t\tbr_ifindex = 0;\n+\t}\n+\n+\tfor (i = 0; i < params->num_bridge; i++) {\n+\t\tif (params->bridge[i]) {\n+\t\t\tifindex = if_nametoindex(params->bridge[i]);\n+\t\t\tif (ifindex)\n+\t\t\t\tadd_ifidx(drv, ifindex);\n+\t\t\tif (ifindex == br_ifindex)\n+\t\t\t\tbr_added = 1;\n+\t\t}\n+\t}\n+\tif (!br_added && br_ifindex &&\n+\t    (params->num_bridge == 0 || !params->bridge[0]))\n+\t\tadd_ifidx(drv, br_ifindex);\n+\n+\t/* start listening for EAPOL on the default AP interface */\n+\tadd_ifidx(drv, drv->ifindex);\n+\n+\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock, bss->ifname, 0))\n+\t\tgoto failed;\n+\n+\tif (params->bssid) {\n+\t\tif (linux_set_fake_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n+\t\t\t\t       params->bssid))\n+\t\t\tgoto failed;\n+\t}\n+\n+\tif (wpa_driver_capwap_set_mode(bss, drv->nlmode)) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Failed to set interface %s \"\n+\t\t\t   \"into AP mode\", bss->ifname);\n+\t\tgoto failed;\n+\t}\n+\n+\tif (params->num_bridge && params->bridge[0] &&\n+\t    i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)\n+\t\tgoto failed;\n+\n+\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock, bss->ifname, 1))\n+\t\tgoto failed;\n+\n+\tdrv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));\n+\tif (drv->eapol_sock < 0) {\n+\t\tperror(\"socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)\");\n+\t\tgoto failed;\n+\t}\n+\n+\tif (linux_get_fake_ifhwaddr(drv->global->ioctl_sock, bss->ifname,  params->own_addr))        goto failed;\n+\n+\tgeneric_ac_info.pseudo_interface = params->ifname;\n+\tvoid (*pointer_inject_frame)(void *, unsigned char*,int);\n+\tpointer_inject_frame = AC_inject_frame_in_hostapd;\n+\t\n+\tgeneric_ac_info.fd_ipc = start_ipc(drv->ctx, pointer_inject_frame);\n+\n+\tcapability_get_mac(generic_ac_info.own_mac_addr);\n+\tmemcpy(drv->addr,generic_ac_info.own_mac_addr, ETH_ALEN);\n+\tmemcpy(params->own_addr,generic_ac_info.own_mac_addr, ETH_ALEN);\n+\tif(generic_ac_info.fd_ipc<=0){\n+\t\twpa_printf(MSG_ERROR, \"Error: start_ipc\");\n+\t\treturn;\n+\t}\n+\n+\treturn bss;\n+\n+failed:\n+\twpa_driver_capwap_deinit(bss);\n+\treturn NULL;\n+}\n+\n+\n+static void i802_deinit(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tipc_send_DEL_WLAN(generic_ac_info.fd_ipc);\n+\tend_ipc(generic_ac_info.fd_ipc);\n+\twpa_driver_capwap_deinit(bss);\n+}\n+\n+#endif /* HOSTAPD */\n+\n+\n+static enum capwap_iftype wpa_driver_capwap_if_type(\n+\tenum wpa_driver_if_type type)\n+{\n+\tswitch (type) {\n+\tcase WPA_IF_STATION:\n+\t\treturn NL80211_IFTYPE_STATION;\n+\tcase WPA_IF_P2P_CLIENT:\n+\tcase WPA_IF_P2P_GROUP:\n+\t\treturn NL80211_IFTYPE_P2P_CLIENT;\n+\tcase WPA_IF_AP_VLAN:\n+\t\treturn NL80211_IFTYPE_AP_VLAN;\n+\tcase WPA_IF_AP_BSS:\n+\t\treturn NL80211_IFTYPE_AP;\n+\tcase WPA_IF_P2P_GO:\n+\t\treturn NL80211_IFTYPE_P2P_GO;\n+\t}\n+\treturn -1;\n+}\n+\n+\n+#ifdef CONFIG_P2P\n+\n+static int capwap_addr_in_use(struct capwap_global *global, const u8 *addr)\n+{\n+\tstruct wpa_driver_capwap_data *drv;\n+\tdl_list_for_each(drv, &global->interfaces,\n+\t\t\t struct wpa_driver_capwap_data, list) {\n+\t\tif (os_memcmp(addr, drv->first_bss.addr, ETH_ALEN) == 0)\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n+\n+static int capwap_p2p_interface_addr(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t      u8 *new_addr)\n+{\n+\tunsigned int idx;\n+\n+\tif (!drv->global)\n+\t\treturn -1;\n+\n+\tos_memcpy(new_addr, drv->first_bss.addr, ETH_ALEN);\n+\tfor (idx = 0; idx < 64; idx++) {\n+\t\tnew_addr[0] = drv->first_bss.addr[0] | 0x02;\n+\t\tnew_addr[0] ^= idx << 2;\n+\t\tif (!capwap_addr_in_use(drv->global, new_addr))\n+\t\t\tbreak;\n+\t}\n+\tif (idx == 64)\n+\t\treturn -1;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Assigned new P2P Interface Address \"\n+\t\t   MACSTR, MAC2STR(new_addr));\n+\n+\treturn 0;\n+}\n+\n+#endif /* CONFIG_P2P */\n+\n+\n+static int wpa_driver_capwap_if_add(void *priv, enum wpa_driver_if_type type,\n+\t\t\t\t     const char *ifname, const u8 *addr,\n+\t\t\t\t     void *bss_ctx, void **drv_priv,\n+\t\t\t\t     char *force_ifname, u8 *if_addr,\n+\t\t\t\t     const char *bridge)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ifidx;\n+#ifdef HOSTAPD\n+\tstruct i802_bss *new_bss = NULL;\n+\n+\tif (type == WPA_IF_AP_BSS) {\n+\t\tnew_bss = os_zalloc(sizeof(*new_bss));\n+\t\tif (new_bss == NULL)\n+\t\t\treturn -1;\n+\t}\n+#endif /* HOSTAPD */\n+\n+\tif (addr)\n+\t\tos_memcpy(if_addr, addr, ETH_ALEN);\n+\tifidx = capwap_create_iface(drv, ifname,\n+\t\t\t\t     wpa_driver_capwap_if_type(type), addr,\n+\t\t\t\t     0);\n+\tif (ifidx < 0) {\n+#ifdef HOSTAPD\n+\t\tos_free(new_bss);\n+#endif /* HOSTAPD */\n+\t\treturn -1;\n+\t}\n+\n+\tif (!addr &&\n+\t    linux_get_fake_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n+\t\t\t       if_addr) < 0) {\n+\t\tcapwap_remove_iface(drv, ifidx);\n+\t\treturn -1;\n+\t}\n+\n+#ifdef CONFIG_P2P\n+\tif (!addr &&\n+\t    (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||\n+\t     type == WPA_IF_P2P_GO)) {\n+\t\t/* Enforce unique P2P Interface Address */\n+\t\tu8 new_addr[ETH_ALEN], own_addr[ETH_ALEN];\n+\n+\t\tif (linux_get_fake_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n+\t\t\t\t       own_addr) < 0 ||\n+\t\t    linux_get_fake_ifhwaddr(drv->global->ioctl_sock, ifname,\n+\t\t\t\t       new_addr) < 0) {\n+\t\t\tcapwap_remove_iface(drv, ifidx);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (os_memcmp(own_addr, new_addr, ETH_ALEN) == 0) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Allocate new address \"\n+\t\t\t\t   \"for P2P group interface\");\n+\t\t\tif (capwap_p2p_interface_addr(drv, new_addr) < 0) {\n+\t\t\t\tcapwap_remove_iface(drv, ifidx);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tif (linux_set_fake_ifhwaddr(drv->global->ioctl_sock, ifname,\n+\t\t\t\t\t       new_addr) < 0) {\n+\t\t\t\tcapwap_remove_iface(drv, ifidx);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t}\n+\t\tos_memcpy(if_addr, new_addr, ETH_ALEN);\n+\t}\n+#endif /* CONFIG_P2P */\n+\n+#ifdef HOSTAPD\n+\tif (bridge &&\n+\t    i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add the new \"\n+\t\t\t   \"interface %s to a bridge %s\", ifname, bridge);\n+\t\tcapwap_remove_iface(drv, ifidx);\n+\t\tos_free(new_bss);\n+\t\treturn -1;\n+\t}\n+\n+\tif (type == WPA_IF_AP_BSS) {\n+\t\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock, ifname, 1))\n+\t\t{\n+\t\t\tcapwap_remove_iface(drv, ifidx);\n+\t\t\tos_free(new_bss);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tos_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);\n+\t\tos_memcpy(new_bss->addr, if_addr, ETH_ALEN);\n+\t\tnew_bss->ifindex = ifidx;\n+\t\tnew_bss->drv = drv;\n+\t\tnew_bss->next = drv->first_bss.next;\n+\t\tnew_bss->freq = drv->first_bss.freq;\n+\t\tnew_bss->ctx = bss_ctx;\n+\t\tdrv->first_bss.next = new_bss;\n+\t\tif (drv_priv)\n+\t\t\t*drv_priv = new_bss;\n+\t\tcapwap_init_bss(new_bss);\n+\n+\t\t/* Subscribe management frames for this WPA_IF_AP_BSS */\n+\t\tif (capwap_setup_ap(new_bss))\n+\t\t\treturn -1;\n+\t}\n+#endif /* HOSTAPD */\n+\n+\tif (drv->global)\n+\t\tdrv->global->if_add_ifindex = ifidx;\n+\n+\treturn 0;\n+}\n+\n+\n+static int wpa_driver_capwap_if_remove(struct i802_bss *bss,\n+\t\t\t\t\tenum wpa_driver_if_type type,\n+\t\t\t\t\tconst char *ifname)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ifindex = if_nametoindex(ifname);\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: %s(type=%d ifname=%s) ifindex=%d\",\n+\t\t   __func__, type, ifname, ifindex);\n+\tif (ifindex <= 0)\n+\t\treturn -1;\n+\n+\tcapwap_remove_iface(drv, ifindex);\n+\n+#ifdef HOSTAPD\n+\tif (type != WPA_IF_AP_BSS)\n+\t\treturn 0;\n+\n+\tif (bss->added_if_into_bridge) {\n+\t\tif (linux_br_fake_del_if(drv->global->ioctl_sock, bss->brname,\n+\t\t\t\t    bss->ifname) < 0)\n+\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n+\t\t\t\t   \"interface %s from bridge %s: %s\",\n+\t\t\t\t   bss->ifname, bss->brname, strerror(errno));\n+\t}\n+\tif (bss->added_bridge) {\n+\t\tif (linux_br_fake_del(drv->global->ioctl_sock, bss->brname) < 0)\n+\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n+\t\t\t\t   \"bridge %s: %s\",\n+\t\t\t\t   bss->brname, strerror(errno));\n+\t}\n+\n+\tif (bss != &drv->first_bss) {\n+\t\tstruct i802_bss *tbss;\n+\n+\t\tfor (tbss = &drv->first_bss; tbss; tbss = tbss->next) {\n+\t\t\tif (tbss->next == bss) {\n+\t\t\t\ttbss->next = bss->next;\n+\t\t\t\t/* Unsubscribe management frames */\n+\t\t\t\tcapwap_teardown_ap(bss);\n+\t\t\t\tcapwap_destroy_bss(bss);\n+\t\t\t\tos_free(bss);\n+\t\t\t\tbss = NULL;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tif (bss)\n+\t\t\twpa_printf(MSG_INFO, \"capwap: %s - could not find \"\n+\t\t\t\t   \"BSS %p in the list\", __func__, bss);\n+\t}\n+#endif /* HOSTAPD */\n+\n+\treturn 0;\n+}\n+\n+\n+static int cookie_handler(struct nl_msg *msg, void *arg)\n+{\n+\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n+\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n+\tu64 *cookie = arg;\n+\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n+\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n+\tif (tb[NL80211_ATTR_COOKIE])\n+\t\t*cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);\n+\treturn NL_SKIP;\n+}\n+\n+\n+static int capwap_send_frame_cmd(struct i802_bss *bss,\n+\t\t\t\t  unsigned int freq, unsigned int wait,\n+\t\t\t\t  const u8 *buf, size_t buf_len,\n+\t\t\t\t  u64 *cookie_out, int no_cck, int no_ack,\n+\t\t\t\t  int offchanok)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tu64 cookie;\n+\tint ret = -1;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: CMD_FRAME freq=%u wait=%u no_cck=%d \"\n+\t\t   \"no_ack=%d offchanok=%d\",\n+\t\t   freq, wait, no_cck, no_ack, offchanok);\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_FRAME);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);\n+\tif (wait)\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);\n+\tif (offchanok && (drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX))\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);\n+\tif (no_cck)\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);\n+\tif (no_ack)\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK);\n+\n+\tNLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);\n+\n+\tcookie = 0;\n+\tret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Frame command failed: ret=%d \"\n+\t\t\t   \"(%s) (freq=%u wait=%u)\", ret, strerror(-ret),\n+\t\t\t   freq, wait);\n+\t\tgoto nla_put_failure;\n+\t}\n+\twpa_printf(MSG_DEBUG, \"capwap: Frame TX command accepted%s; \"\n+\t\t   \"cookie 0x%llx\", no_ack ? \" (no ACK)\" : \"\",\n+\t\t   (long long unsigned int) cookie);\n+\n+\tif (cookie_out)\n+\t\t*cookie_out = no_ack ? (u64) -1 : cookie;\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int wpa_driver_capwap_send_action(struct i802_bss *bss,\n+\t\t\t\t\t  unsigned int freq,\n+\t\t\t\t\t  unsigned int wait_time,\n+\t\t\t\t\t  const u8 *dst, const u8 *src,\n+\t\t\t\t\t  const u8 *bssid,\n+\t\t\t\t\t  const u8 *data, size_t data_len,\n+\t\t\t\t\t  int no_cck)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret = -1;\n+\tu8 *buf;\n+\tstruct ieee80211_hdr *hdr;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Send Action frame (ifindex=%d, \"\n+\t\t   \"freq=%u MHz wait=%d ms no_cck=%d)\",\n+\t\t   drv->ifindex, freq, wait_time, no_cck);\n+\n+\tbuf = os_zalloc(24 + data_len);\n+\tif (buf == NULL)\n+\t\treturn ret;\n+\tos_memcpy(buf + 24, data, data_len);\n+\thdr = (struct ieee80211_hdr *) buf;\n+\thdr->frame_control =\n+\t\tIEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);\n+\tos_memcpy(hdr->addr1, dst, ETH_ALEN);\n+\tos_memcpy(hdr->addr2, src, ETH_ALEN);\n+\tos_memcpy(hdr->addr3, bssid, ETH_ALEN);\n+\n+\tif (is_ap_interface(drv->nlmode))\n+\t\tret = wpa_driver_capwap_send_mlme(bss, buf, 24 + data_len,\n+\t\t\t\t\t\t   0, freq, no_cck, 1,\n+\t\t\t\t\t\t   wait_time);\n+\telse\n+\t\tret = capwap_send_frame_cmd(bss, freq, wait_time, buf,\n+\t\t\t\t\t     24 + data_len,\n+\t\t\t\t\t     &drv->send_action_cookie,\n+\t\t\t\t\t     no_cck, 0, 1);\n+\n+\tos_free(buf);\n+\treturn ret;\n+}\n+\n+\n+static void wpa_driver_capwap_send_action_cancel_wait(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Cancel TX frame wait: cookie=0x%llx\",\n+\t\t   (long long unsigned int) drv->send_action_cookie);\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: wait cancel failed: ret=%d \"\n+\t\t\t   \"(%s)\", ret, strerror(-ret));\n+\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+}\n+\n+\n+static int wpa_driver_capwap_remain_on_channel(void *priv, unsigned int freq,\n+\t\t\t\t\t\tunsigned int duration)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret;\n+\tu64 cookie;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);\n+\n+\tcookie = 0;\n+\tret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);\n+\tmsg = NULL;\n+\tif (ret == 0) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Remain-on-channel cookie \"\n+\t\t\t   \"0x%llx for freq=%u MHz duration=%u\",\n+\t\t\t   (long long unsigned int) cookie, freq, duration);\n+\t\tdrv->remain_on_chan_cookie = cookie;\n+\t\tdrv->pending_remain_on_chan = 1;\n+\t\treturn 0;\n+\t}\n+\twpa_printf(MSG_DEBUG, \"capwap: Failed to request remain-on-channel \"\n+\t\t   \"(freq=%d duration=%u): %d (%s)\",\n+\t\t   freq, duration, ret, strerror(-ret));\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -1;\n+}\n+\n+\n+static int wpa_driver_capwap_cancel_remain_on_channel(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tint ret;\n+\n+\tif (!drv->pending_remain_on_chan) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: No pending remain-on-channel \"\n+\t\t\t   \"to cancel\");\n+\t\treturn -1;\n+\t}\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Cancel remain-on-channel with cookie \"\n+\t\t   \"0x%llx\",\n+\t\t   (long long unsigned int) drv->remain_on_chan_cookie);\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret == 0)\n+\t\treturn 0;\n+\twpa_printf(MSG_DEBUG, \"capwap: Failed to cancel remain-on-channel: \"\n+\t\t   \"%d (%s)\", ret, strerror(-ret));\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -1;\n+}\n+\n+\n+static int wpa_driver_capwap_probe_req_report(struct i802_bss *bss, int report)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\tif (!report) {\n+\t\tif (bss->nl_preq && drv->device_ap_sme &&\n+\t\t    is_ap_interface(drv->nlmode)) {\n+\t\t\t/*\n+\t\t\t * Do not disable Probe Request reporting that was\n+\t\t\t * enabled in capwap_setup_ap().\n+\t\t\t */\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Skip disabling of \"\n+\t\t\t\t   \"Probe Request reporting nl_preq=%p while \"\n+\t\t\t\t   \"in AP mode\", bss->nl_preq);\n+\t\t} else if (bss->nl_preq) {\n+\t\t\twpa_printf(MSG_DEBUG, \"capwap: Disable Probe Request \"\n+\t\t\t\t   \"reporting nl_preq=%p\", bss->nl_preq);\n+\t\t\teloop_unregister_read_sock(\n+\t\t\t\tnl_socket_get_fd(bss->nl_preq));\n+\t\t        nl_destroy_cache(&bss->nl_preq_cache);\n+\t\t\tnl_destroy_handles(&bss->nl_preq);\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\tif (bss->nl_preq) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Probe Request reporting \"\n+\t\t\t   \"already on! nl_preq=%p\", bss->nl_preq);\n+\t\treturn 0;\n+\t}\n+\n+\tbss->nl_preq = nl_create_handle(drv->global->nl_cb, \"preq\");\n+        bss->nl_preq_cache = nl_create_cache(bss->nl_preq);\n+\tif (bss->nl_preq == NULL)\n+\t\treturn -1;\n+\twpa_printf(MSG_DEBUG, \"capwap: Enable Probe Request \"\n+\t\t   \"reporting nl_preq=%p\", bss->nl_preq);\n+\n+\tif (capwap_register_frame(bss, bss->nl_preq,\n+\t\t\t\t   (WLAN_FC_TYPE_MGMT << 2) |\n+\t\t\t\t   (WLAN_FC_STYPE_PROBE_REQ << 4),\n+\t\t\t\t   NULL, 0) < 0)\n+\t\tgoto out_err;\n+\n+\teloop_register_read_sock(nl_socket_get_fd(bss->nl_preq),\n+\t\t\t\t wpa_driver_capwap_event_receive, bss->nl_cb,\n+\t\t\t\t bss->nl_preq);\n+\n+\treturn 0;\n+\n+ out_err:\n+        nl_destroy_cache(&bss->nl_preq_cache);\n+\tnl_destroy_handles(&bss->nl_preq);\n+\treturn -1;\n+}\n+\n+\n+static int capwap_disable_11b_rates(struct wpa_driver_capwap_data *drv,\n+\t\t\t\t     int ifindex, int disabled)\n+{\n+\tstruct nl_msg *msg;\n+\tstruct nlattr *bands, *band;\n+\tint ret;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n+\n+\tbands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);\n+\tif (!bands)\n+\t\tgoto nla_put_failure;\n+\n+\t/*\n+\t * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything\n+\t * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS\n+\t * rates. All 5 GHz rates are left enabled.\n+\t */\n+\tband = nla_nest_start(msg, NL80211_BAND_2GHZ);\n+\tif (!band)\n+\t\tgoto nla_put_failure;\n+\tif (disabled) {\n+\t\tNLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,\n+\t\t\t\"\\x0c\\x12\\x18\\x24\\x30\\x48\\x60\\x6c\");\n+\t}\n+\tnla_nest_end(msg, band);\n+\n+\tnla_nest_end(msg, bands);\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\tif (ret) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Set TX rates failed: ret=%d \"\n+\t\t\t   \"(%s)\", ret, strerror(-ret));\n+\t} else\n+\t\tdrv->disabled_11b_rates = disabled;\n+\n+\treturn ret;\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -1;\n+}\n+\n+\n+static int wpa_driver_capwap_deinit_ap(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tif (!is_ap_interface(drv->nlmode))\n+\t\treturn -1;\n+\twpa_driver_capwap_del_beacon(drv);\n+\treturn wpa_driver_capwap_set_mode(priv, NL80211_IFTYPE_STATION);\n+}\n+\n+static int wpa_driver_capwap_deinit_p2p_cli(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tif (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)\n+\t\treturn -1;\n+\treturn wpa_driver_capwap_set_mode(priv, NL80211_IFTYPE_STATION);\n+}\n+\n+\n+static void wpa_driver_capwap_resume(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tif (linux_set_fake_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to set interface up on \"\n+\t\t\t   \"resume event\");\n+\t}\n+}\n+\n+\n+static int capwap_send_ft_action(void *priv, u8 action, const u8 *target_ap,\n+\t\t\t\t  const u8 *ies, size_t ies_len)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint ret;\n+\tu8 *data, *pos;\n+\tsize_t data_len;\n+\tconst u8 *own_addr = bss->addr;\n+\n+\tif (action != 1) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: Unsupported send_ft_action \"\n+\t\t\t   \"action %d\", action);\n+\t\treturn -1;\n+\t}\n+\n+\t/*\n+\t * Action frame payload:\n+\t * Category[1] = 6 (Fast BSS Transition)\n+\t * Action[1] = 1 (Fast BSS Transition Request)\n+\t * STA Address\n+\t * Target AP Address\n+\t * FT IEs\n+\t */\n+\n+\tdata_len = 2 + 2 * ETH_ALEN + ies_len;\n+\tdata = os_malloc(data_len);\n+\tif (data == NULL)\n+\t\treturn -1;\n+\tpos = data;\n+\t*pos++ = 0x06; /* FT Action category */\n+\t*pos++ = action;\n+\tos_memcpy(pos, own_addr, ETH_ALEN);\n+\tpos += ETH_ALEN;\n+\tos_memcpy(pos, target_ap, ETH_ALEN);\n+\tpos += ETH_ALEN;\n+\tos_memcpy(pos, ies, ies_len);\n+\n+\tret = wpa_driver_capwap_send_action(bss, drv->assoc_freq, 0,\n+\t\t\t\t\t     drv->bssid, own_addr, drv->bssid,\n+\t\t\t\t\t     data, data_len, 0);\n+\tos_free(data);\n+\n+\treturn ret;\n+}\n+\n+\n+static int capwap_signal_monitor(void *priv, int threshold, int hysteresis)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg, *cqm = NULL;\n+\tint ret = -1;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: Signal monitor threshold=%d \"\n+\t\t   \"hysteresis=%d\", threshold, hysteresis);\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -1;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\n+\tcqm = nlmsg_alloc();\n+\tif (cqm == NULL)\n+\t\tgoto nla_put_failure;\n+\n+\tNLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold);\n+\tNLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);\n+\tif (nla_put_nested(msg, NL80211_ATTR_CQM, cqm) < 0)\n+\t\tgoto nla_put_failure;\n+\n+\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n+\tmsg = NULL;\n+\n+nla_put_failure:\n+\tnlmsg_free(cqm);\n+\tnlmsg_free(msg);\n+\treturn ret;\n+}\n+\n+\n+static int capwap_signal_poll(void *priv, struct wpa_signal_info *si)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tint res;\n+\n+\tos_memset(si, 0, sizeof(*si));\n+\tres = capwap_get_link_signal(drv, si);\n+\tif (res != 0)\n+\t\treturn res;\n+\n+\treturn capwap_get_link_noise(drv, si);\n+}\n+\n+\n+static int wpa_driver_capwap_shared_freq(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct wpa_driver_capwap_data *driver;\n+\tint freq = 0;\n+\n+\t/*\n+\t * If the same PHY is in connected state with some other interface,\n+\t * then retrieve the assoc freq.\n+\t */\n+\twpa_printf(MSG_DEBUG, \"capwap: Get shared freq for PHY %s\",\n+\t\t   drv->phyname);\n+\n+\tdl_list_for_each(driver, &drv->global->interfaces,\n+\t\t\t struct wpa_driver_capwap_data, list) {\n+\t\tif (drv == driver ||\n+\t\t    os_strcmp(drv->phyname, driver->phyname) != 0 ||\n+\t\t    !driver->associated)\n+\t\t\tcontinue;\n+\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Found a match for PHY %s - %s \"\n+\t\t\t   MACSTR,\n+\t\t\t   driver->phyname, driver->first_bss.ifname,\n+\t\t\t   MAC2STR(driver->first_bss.addr));\n+\t\tif (is_ap_interface(driver->nlmode))\n+\t\t\tfreq = driver->first_bss.freq;\n+\t\telse\n+\t\t\tfreq = capwap_get_assoc_freq(driver);\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Shared freq for PHY %s: %d\",\n+\t\t\t   drv->phyname, freq);\n+\t}\n+\n+\tif (!freq)\n+\t\twpa_printf(MSG_DEBUG, \"capwap: No shared interface for \"\n+\t\t\t   \"PHY (%s) in associated state\", drv->phyname);\n+\n+\treturn freq;\n+}\n+\n+\n+static int capwap_send_frame(void *priv, const u8 *data, size_t data_len,\n+\t\t\t      int encrypt)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_send_frame(bss, data, data_len, encrypt, 0,\n+\t\t\t\t\t     0, 0, 0, 0);\n+}\n+\n+\n+static int capwap_set_param(void *priv, const char *param)\n+{\n+\twpa_printf(MSG_DEBUG, \"capwap: driver param='%s'\", param);\n+\tif (param == NULL)\n+\t\treturn 0;\n+\n+#ifdef CONFIG_P2P\n+\tif (os_strstr(param, \"use_p2p_group_interface=1\")) {\n+\t\tstruct i802_bss *bss = priv;\n+\t\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\t\twpa_printf(MSG_DEBUG, \"capwap: Use separate P2P group \"\n+\t\t\t   \"interface\");\n+\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;\n+\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;\n+\t}\n+#endif /* CONFIG_P2P */\n+\n+\treturn 0;\n+}\n+\n+\n+static void * capwap_global_init(void)\n+{\n+\twpa_printf(MSG_DEBUG,\"                          1.capwap_global_init\\n\");\n+\tstruct capwap_global *global;\n+\tstruct netlink_config *cfg;\n+\n+\tglobal = os_zalloc(sizeof(*global));\n+\tif (global == NULL)\n+\t\treturn NULL;\n+\tglobal->ioctl_sock = -1;\n+\tdl_list_init(&global->interfaces);\n+\tglobal->if_add_ifindex = -1;\n+\n+\tcfg = os_zalloc(sizeof(*cfg));\n+\tif (cfg == NULL)\n+\t\tgoto err;\n+\n+\tcfg->ctx = global;\n+\tcfg->newlink_cb = wpa_driver_capwap_event_rtm_newlink;\n+\tcfg->dellink_cb = wpa_driver_capwap_event_rtm_dellink;\n+\tglobal->netlink = netlink_fake_init(cfg);\n+\tif (global->netlink == NULL) {\n+\t\tos_free(cfg);\n+\t\tgoto err;\n+\t}\n+\n+\tif (wpa_driver_capwap_init_nl_global(global) < 0)\n+\t\tgoto err;\n+\n+\tglobal->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);\n+\tif (global->ioctl_sock < 0) {\n+\t\tperror(\"socket(PF_INET,SOCK_DGRAM)\");\n+\t\tgoto err;\n+\t}\n+\n+\treturn global;\n+\n+err:\n+\tcapwap_global_deinit(global);\n+\treturn NULL;\n+}\n+\n+\n+static void capwap_global_deinit(void *priv)\n+{\n+\tstruct capwap_global *global = priv;\n+\tif (global == NULL)\n+\t\treturn;\n+\tif (!dl_list_empty(&global->interfaces)) {\n+\t\twpa_printf(MSG_ERROR, \"capwap: %u interface(s) remain at \"\n+\t\t\t   \"capwap_global_deinit\",\n+\t\t\t   dl_list_len(&global->interfaces));\n+\t}\n+\n+\tif (global->netlink)\n+\t\tnetlink_deinit(global->netlink);\n+\tif (global->capwap)\n+\t\tgenl_family_put(global->capwap);\n+\n+\n+        nl_destroy_cache(&global->nl_cache);\n+\tnl_destroy_handles(&global->nl);\n+\n+\tif (global->nl_event) {\n+\t\teloop_unregister_read_sock(\n+\t\t\tnl_socket_get_fd(global->nl_event));\n+        \tnl_destroy_cache(&global->nl_event_cache);\n+\t\tnl_destroy_handles(&global->nl_event);\n+\t}\n+\n+\tnl_cb_put(global->nl_cb);\n+\n+\tif (global->ioctl_sock >= 0)\n+\t\tclose(global->ioctl_sock);\n+\n+\tos_free(global);\n+}\n+\n+\n+static const char * capwap_get_radio_name(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\treturn drv->phyname;\n+}\n+\n+\n+static int capwap_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,\n+\t\t\t const u8 *pmkid)\n+{\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(bss->drv, msg, 0, cmd);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n+\tif (pmkid)\n+\t\tNLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid);\n+\tif (bssid)\n+\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);\n+\n+\treturn send_and_recv_msgs(bss->drv, msg, NULL, NULL);\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int capwap_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)\n+{\n+\tstruct i802_bss *bss = priv;\n+\twpa_printf(MSG_DEBUG, \"capwap: Add PMKID for \" MACSTR, MAC2STR(bssid));\n+\treturn capwap_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);\n+}\n+\n+\n+static int capwap_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)\n+{\n+\tstruct i802_bss *bss = priv;\n+\twpa_printf(MSG_DEBUG, \"capwap: Delete PMKID for \" MACSTR,\n+\t\t   MAC2STR(bssid));\n+\treturn capwap_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);\n+}\n+\n+\n+static int capwap_flush_pmkid(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\twpa_printf(MSG_DEBUG, \"capwap: Flush PMKIDs\");\n+\treturn capwap_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);\n+}\n+\n+\n+static void capwap_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,\n+\t\t\t\t   const u8 *replay_ctr)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nlattr *replay_nested;\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\n+\treplay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);\n+\tif (!replay_nested)\n+\t\tgoto nla_put_failure;\n+\n+\tNLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);\n+\tNLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);\n+\tNLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,\n+\t\treplay_ctr);\n+\n+\tnla_nest_end(msg, replay_nested);\n+\n+\tsend_and_recv_msgs(drv, msg, NULL, NULL);\n+\treturn;\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+}\n+\n+\n+static void capwap_send_null_frame(struct i802_bss *bss, const u8 *own_addr,\n+\t\t\t\t    const u8 *addr, int qos)\n+{\n+\t/* send data frame to poll STA and check whether\n+\t * this frame is ACKed */\n+\tstruct {\n+\t\tstruct ieee80211_hdr hdr;\n+\t\tu16 qos_ctl;\n+\t} STRUCT_PACKED nulldata;\n+\tsize_t size;\n+\n+\t/* Send data frame to poll STA and check whether this frame is ACKed */\n+\n+\tos_memset(&nulldata, 0, sizeof(nulldata));\n+\n+\tif (qos) {\n+\t\tnulldata.hdr.frame_control =\n+\t\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA,\n+\t\t\t\t     WLAN_FC_STYPE_QOS_NULL);\n+\t\tsize = sizeof(nulldata);\n+\t} else {\n+\t\tnulldata.hdr.frame_control =\n+\t\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA,\n+\t\t\t\t     WLAN_FC_STYPE_NULLFUNC);\n+\t\tsize = sizeof(struct ieee80211_hdr);\n+\t}\n+\n+\tnulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);\n+\tos_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);\n+\tos_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);\n+\tos_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);\n+\n+\tif (wpa_driver_capwap_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,\n+\t\t\t\t\t 0, 0) < 0)\n+\t\twpa_printf(MSG_DEBUG, \"capwap_send_null_frame: Failed to \"\n+\t\t\t   \"send poll frame\");\n+}\n+\n+static void capwap_poll_client(void *priv, const u8 *own_addr, const u8 *addr,\n+\t\t\t\tint qos)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\n+\tif (!drv->poll_command_supported) {\n+\t\tcapwap_send_null_frame(bss, own_addr, addr, qos);\n+\t\treturn;\n+\t}\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT);\n+\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n+\n+\tsend_and_recv_msgs(drv, msg, NULL, NULL);\n+\treturn;\n+ nla_put_failure:\n+\tnlmsg_free(msg);\n+}\n+\n+\n+static int capwap_set_power_save(struct i802_bss *bss, int enabled)\n+{\n+\tstruct nl_msg *msg;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(bss->drv, msg, 0, NL80211_CMD_SET_POWER_SAVE);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_PS_STATE,\n+\t\t    enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);\n+\treturn send_and_recv_msgs(bss->drv, msg, NULL, NULL);\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int capwap_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,\n+\t\t\t\t     int ctwindow)\n+{\n+\tstruct i802_bss *bss = priv;\n+\n+\twpa_printf(MSG_DEBUG, \"capwap: set_p2p_powersave (legacy_ps=%d \"\n+\t\t   \"opp_ps=%d ctwindow=%d)\", legacy_ps, opp_ps, ctwindow);\n+\n+\tif (opp_ps != -1 || ctwindow != -1)\n+\t\treturn -1; /* Not yet supported */\n+\n+\tif (legacy_ps == -1)\n+\t\treturn 0;\n+\tif (legacy_ps != 0 && legacy_ps != 1)\n+\t\treturn -1; /* Not yet supported */\n+\n+\treturn capwap_set_power_save(bss, legacy_ps);\n+}\n+\n+\n+#ifdef CONFIG_TDLS\n+\n+static int capwap_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,\n+\t\t\t\t  u8 dialog_token, u16 status_code,\n+\t\t\t\t  const u8 *buf, size_t len)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\n+\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tif (!dst)\n+\t\treturn -EINVAL;\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);\n+\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);\n+\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);\n+\tNLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);\n+\tNLA_PUT(msg, NL80211_ATTR_IE, len, buf);\n+\n+\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+\n+static int capwap_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)\n+{\n+\tstruct i802_bss *bss = priv;\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct nl_msg *msg;\n+\tenum nl80211_tdls_operation capwap_oper;\n+\n+\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tswitch (oper) {\n+\tcase TDLS_DISCOVERY_REQ:\n+\t\tcapwap_oper = NL80211_TDLS_DISCOVERY_REQ;\n+\t\tbreak;\n+\tcase TDLS_SETUP:\n+\t\tcapwap_oper = NL80211_TDLS_SETUP;\n+\t\tbreak;\n+\tcase TDLS_TEARDOWN:\n+\t\tcapwap_oper = NL80211_TDLS_TEARDOWN;\n+\t\tbreak;\n+\tcase TDLS_ENABLE_LINK:\n+\t\tcapwap_oper = NL80211_TDLS_ENABLE_LINK;\n+\t\tbreak;\n+\tcase TDLS_DISABLE_LINK:\n+\t\tcapwap_oper = NL80211_TDLS_DISABLE_LINK;\n+\t\tbreak;\n+\tcase TDLS_ENABLE:\n+\t\treturn 0;\n+\tcase TDLS_DISABLE:\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmsg = nlmsg_alloc();\n+\tif (!msg)\n+\t\treturn -ENOMEM;\n+\n+\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);\n+\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, capwap_oper);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);\n+\n+\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n+\n+nla_put_failure:\n+\tnlmsg_free(msg);\n+\treturn -ENOBUFS;\n+}\n+\n+#endif /* CONFIG TDLS */\n+\n+void AC_inject_frame_in_hostapd(void *priv, u8 *buf, int len){\n+\n+       struct i802_bss *bss = priv;\n+       struct wpa_driver_capwap_data *drv = bss->drv;\n+\n+\tint ret;\n+\tint datarate = 0, ssi_signal = 0;\n+\tint failed = 0, rxflags = 0;\n+\n+\n+\tif (len < 24) {\n+\t\tperror(\"recv\");\n+\t\treturn;\n+\t}\n+\n+\tint type = AC_get_Type(buf ,len );\n+\n+\n+\tif( type == WLAN_FC_TYPE_DATA ){\n+\n+               if( isEAPOL_Frame(buf, len) ){\n+\t\t\tif(isCallBackFrame(buf,len,generic_ac_info.own_mac_addr)) {\n+\t\t\t\twpa_printf(MSG_DEBUG, \"EAPOL Data Frame 4 (%d)\\n\",len);\n+\t\t\t\thandle_tx_callback(drv->ctx, buf ,len , !failed);\n+\t\t\t}else{\n+\t\t\t\twpa_printf(MSG_DEBUG, \"EAPOL Data Frame 6 (%d)\\n\",len);\n+\t\t\t\tAC_handle_eapol(drv,buf,len);\n+\t\t\t}\n+               }else{\n+\t\t\thandle_frame(drv, buf , len , datarate, ssi_signal);\n+               }\n+\n+\t\tint stype = AC_get_SubType(buf ,len );\n+\n+\t\t/* Per ora scarto i pacchetti PROBE REQUEST */\n+\t\tif(stype == WLAN_FC_STYPE_PROBE_REQ) {\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tif(isCallBackFrame(buf,len,generic_ac_info.own_mac_addr)) {\n+\t\t\thandle_tx_callback(drv->ctx, buf ,len , !failed);\n+\n+\t\t\tif( stype == WLAN_FC_STYPE_ASSOC_RESP || stype == WLAN_FC_STYPE_REASSOC_RESP ){\n+\t\t\t\tipc_send_add_station(generic_ac_info.fd_ipc,buf,len);\n+\t\t\t}\n+\t\t}else{\n+\t\t\thandle_frame(drv, buf , len , datarate, ssi_signal);\n+\n+\t\t\tif( stype == WLAN_FC_STYPE_DISASSOC ){\n+\t\t\t\tipc_send_del_station(generic_ac_info.fd_ipc, buf, len);\n+\t\t\t}\n+\t\t}\n+\t}else{\n+\t\twpa_printf(MSG_ERROR,\"Error: invalid/control 802.11 Type \");\n+\t}\n+\n+}\n+\n+#ifdef ANDROID\n+\n+typedef struct android_wifi_priv_cmd {\n+\tchar *buf;\n+\tint used_len;\n+\tint total_len;\n+} android_wifi_priv_cmd;\n+\n+static int drv_errors = 0;\n+\n+static void wpa_driver_send_hang_msg(struct wpa_driver_capwap_data *drv)\n+{\n+\tdrv_errors++;\n+\tif (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {\n+\t\tdrv_errors = 0;\n+\t\twpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE \"HANGED\");\n+\t}\n+}\n+\n+\n+static int android_priv_cmd(struct i802_bss *bss, const char *cmd)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct ifreq ifr;\n+\tandroid_wifi_priv_cmd priv_cmd;\n+\tchar buf[MAX_DRV_CMD_SIZE];\n+\tint ret;\n+\n+\tos_memset(&ifr, 0, sizeof(ifr));\n+\tos_memset(&priv_cmd, 0, sizeof(priv_cmd));\n+\tos_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);\n+\n+\tos_memset(buf, 0, sizeof(buf));\n+\tos_strlcpy(buf, cmd, sizeof(buf));\n+\n+\tpriv_cmd.buf = buf;\n+\tpriv_cmd.used_len = sizeof(buf);\n+\tpriv_cmd.total_len = sizeof(buf);\n+\tifr.ifr_data = &priv_cmd;\n+\n+\tret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_ERROR, \"%s: failed to issue private commands\",\n+\t\t\t   __func__);\n+\t\twpa_driver_send_hang_msg(drv);\n+\t\treturn ret;\n+\t}\n+\n+\tdrv_errors = 0;\n+\treturn 0;\n+}\n+\n+\n+static int android_pno_start(struct i802_bss *bss,\n+\t\t\t     struct wpa_driver_scan_params *params)\n+{\n+\tstruct wpa_driver_capwap_data *drv = bss->drv;\n+\tstruct ifreq ifr;\n+\tandroid_wifi_priv_cmd priv_cmd;\n+\tint ret = 0, i = 0, bp;\n+\tchar buf[WEXT_PNO_MAX_COMMAND_SIZE];\n+\n+\tbp = WEXT_PNOSETUP_HEADER_SIZE;\n+\tos_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);\n+\tbuf[bp++] = WEXT_PNO_TLV_PREFIX;\n+\tbuf[bp++] = WEXT_PNO_TLV_VERSION;\n+\tbuf[bp++] = WEXT_PNO_TLV_SUBVERSION;\n+\tbuf[bp++] = WEXT_PNO_TLV_RESERVED;\n+\n+\twhile (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {\n+\t\t/* Check that there is enough space needed for 1 more SSID, the\n+\t\t * other sections and null termination */\n+\t\tif ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +\n+\t\t     WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))\n+\t\t\tbreak;\n+\t\twpa_hexdump_ascii(MSG_DEBUG, \"For PNO Scan\",\n+\t\t\t\t  params->ssids[i].ssid,\n+\t\t\t\t  params->ssids[i].ssid_len);\n+\t\tbuf[bp++] = WEXT_PNO_SSID_SECTION;\n+\t\tbuf[bp++] = params->ssids[i].ssid_len;\n+\t\tos_memcpy(&buf[bp], params->ssids[i].ssid,\n+\t\t\t  params->ssids[i].ssid_len);\n+\t\tbp += params->ssids[i].ssid_len;\n+\t\ti++;\n+\t}\n+\n+\tbuf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;\n+\tos_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, \"%x\",\n+\t\t    WEXT_PNO_SCAN_INTERVAL);\n+\tbp += WEXT_PNO_SCAN_INTERVAL_LENGTH;\n+\n+\tbuf[bp++] = WEXT_PNO_REPEAT_SECTION;\n+\tos_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, \"%x\",\n+\t\t    WEXT_PNO_REPEAT);\n+\tbp += WEXT_PNO_REPEAT_LENGTH;\n+\n+\tbuf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;\n+\tos_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, \"%x\",\n+\t\t    WEXT_PNO_MAX_REPEAT);\n+\tbp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;\n+\n+\tmemset(&ifr, 0, sizeof(ifr));\n+\tmemset(&priv_cmd, 0, sizeof(priv_cmd));\n+\tos_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);\n+\n+\tpriv_cmd.buf = buf;\n+\tpriv_cmd.used_len = bp;\n+\tpriv_cmd.total_len = bp;\n+\tifr.ifr_data = &priv_cmd;\n+\n+\tret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);\n+\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_ERROR, \"ioctl[SIOCSIWPRIV] (pnosetup): %d\",\n+\t\t\t   ret);\n+\t\twpa_driver_send_hang_msg(drv);\n+\t\treturn ret;\n+\t}\n+\n+\tdrv_errors = 0;\n+\n+\treturn android_priv_cmd(bss, \"PNOFORCE 1\");\n+}\n+\n+\n+static int android_pno_stop(struct i802_bss *bss)\n+{\n+\treturn android_priv_cmd(bss, \"PNOFORCE 0\");\n+}\n+\n+#endif /* ANDROID */\n+\n+\n+static int driver_capwap_set_key(const char *ifname, void *priv,\n+\t\t\t\t  enum wpa_alg alg, const u8 *addr,\n+\t\t\t\t  int key_idx, int set_tx,\n+\t\t\t\t  const u8 *seq, size_t seq_len,\n+\t\t\t\t  const u8 *key, size_t key_len)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_set_key(ifname, bss, alg, addr, key_idx,\n+\t\t\t\t\t  set_tx, seq, seq_len, key, key_len);\n+}\n+\n+\n+static int driver_capwap_scan2(void *priv,\n+\t\t\t\tstruct wpa_driver_scan_params *params)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_scan(bss, params);\n+}\n+\n+\n+static int driver_capwap_deauthenticate(void *priv, const u8 *addr,\n+\t\t\t\t\t int reason_code)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_deauthenticate(bss, addr, reason_code);\n+}\n+\n+\n+static int driver_capwap_authenticate(void *priv,\n+\t\t\t\t       struct wpa_driver_auth_params *params)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_authenticate(bss, params);\n+}\n+\n+\n+static void driver_capwap_deinit(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\twpa_driver_capwap_deinit(bss);\n+}\n+\n+\n+static int driver_capwap_if_remove(void *priv, enum wpa_driver_if_type type,\n+\t\t\t\t    const char *ifname)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_if_remove(bss, type, ifname);\n+}\n+\n+\n+static int driver_capwap_send_mlme(void *priv, const u8 *data,\n+\t\t\t\t    size_t data_len, int noack)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_send_mlme(bss, data, data_len, noack,\n+\t\t\t\t\t    0, 0, 0, 0);\n+}\n+\n+\n+static int driver_capwap_sta_remove(void *priv, const u8 *addr)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_sta_remove(bss, addr);\n+}\n+\n+\n+#if defined(HOSTAPD) || defined(CONFIG_AP)\n+static int driver_capwap_set_sta_vlan(void *priv, const u8 *addr,\n+\t\t\t\t       const char *ifname, int vlan_id)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn i802_set_sta_vlan(bss, addr, ifname, vlan_id);\n+}\n+#endif /* HOSTAPD || CONFIG_AP */\n+\n+\n+static int driver_capwap_read_sta_data(void *priv,\n+\t\t\t\t\tstruct hostap_sta_driver_data *data,\n+\t\t\t\t\tconst u8 *addr)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn i802_read_sta_data(bss, data, addr);\n+}\n+\n+\n+static int driver_capwap_send_action(void *priv, unsigned int freq,\n+\t\t\t\t      unsigned int wait_time,\n+\t\t\t\t      const u8 *dst, const u8 *src,\n+\t\t\t\t      const u8 *bssid,\n+\t\t\t\t      const u8 *data, size_t data_len,\n+\t\t\t\t      int no_cck)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_send_action(bss, freq, wait_time, dst, src,\n+\t\t\t\t\t      bssid, data, data_len, no_cck);\n+}\n+\n+\n+static int driver_capwap_probe_req_report(void *priv, int report)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_capwap_probe_req_report(bss, report);\n+}\n+\n+\n+const struct wpa_driver_ops wpa_driver_capwap_ops = {\n+\t.name = \"capwap\",\n+\t.desc = \"Linux capwap/cfg80211\",\n+\t.get_bssid = wpa_driver_capwap_get_bssid,\n+\t.get_ssid = wpa_driver_capwap_get_ssid,\n+\t.set_key = driver_capwap_set_key,\n+\t.scan2 = driver_capwap_scan2,\n+\t.sched_scan = wpa_driver_capwap_sched_scan,\n+\t.stop_sched_scan = wpa_driver_capwap_stop_sched_scan,\n+\t.get_scan_results2 = wpa_driver_capwap_get_scan_results,\n+\t.deauthenticate = driver_capwap_deauthenticate,\n+\t.authenticate = driver_capwap_authenticate,\n+\t.associate = wpa_driver_capwap_associate,\n+\t.global_init = capwap_global_init,\n+\t.global_deinit = capwap_global_deinit,\n+\t.init2 = wpa_driver_capwap_init,\n+\t.deinit = driver_capwap_deinit,\n+\t.get_capa = wpa_driver_capwap_get_capa,\n+\t.set_operstate = wpa_driver_capwap_set_operstate,\n+\t.set_supp_port = wpa_driver_capwap_set_supp_port,\n+\t.set_country = wpa_driver_capwap_set_country,\n+\t.set_ap = wpa_driver_capwap_set_ap,\n+\t.if_add = wpa_driver_capwap_if_add,\n+\t.if_remove = driver_capwap_if_remove,\n+\t.send_mlme = driver_capwap_send_mlme,\n+\t.get_hw_feature_data = wpa_driver_capwap_get_hw_feature_data,\n+\t.sta_add = wpa_driver_capwap_sta_add,\n+\t.sta_remove = driver_capwap_sta_remove,\n+\t.hapd_send_eapol = wpa_driver_capwap_hapd_send_eapol,\n+\t.sta_set_flags = wpa_driver_capwap_sta_set_flags,\n+\t//.inject_frame_in_hostapd = AC_inject_frame_in_hostapd,\n+#ifdef HOSTAPD\n+\t.hapd_init = i802_init,\n+\t.hapd_deinit = i802_deinit,\n+\t.set_wds_sta = i802_set_wds_sta,\n+#endif /* HOSTAPD */\n+#if defined(HOSTAPD) || defined(CONFIG_AP)\n+\t.get_seqnum = i802_get_seqnum,\n+\t.flush = i802_flush,\n+\t.get_inact_sec = i802_get_inact_sec,\n+\t.sta_clear_stats = i802_sta_clear_stats,\n+\t.set_rts = i802_set_rts,\n+\t.set_frag = i802_set_frag,\n+\t.set_tx_queue_params = i802_set_tx_queue_params,\n+\t.set_sta_vlan = driver_capwap_set_sta_vlan,\n+\t.sta_deauth = i802_sta_deauth,\n+\t.sta_disassoc = i802_sta_disassoc,\n+#endif /* HOSTAPD || CONFIG_AP */\n+\t.read_sta_data = driver_capwap_read_sta_data,\n+\t.set_freq = i802_set_freq,\n+\t.send_action = driver_capwap_send_action,\n+\t.send_action_cancel_wait = wpa_driver_capwap_send_action_cancel_wait,\n+\t.remain_on_channel = wpa_driver_capwap_remain_on_channel,\n+\t.cancel_remain_on_channel =\n+\twpa_driver_capwap_cancel_remain_on_channel,\n+\t.probe_req_report = driver_capwap_probe_req_report,\n+\t.deinit_ap = wpa_driver_capwap_deinit_ap,\n+\t.deinit_p2p_cli = wpa_driver_capwap_deinit_p2p_cli,\n+\t.resume = wpa_driver_capwap_resume,\n+\t.send_ft_action = capwap_send_ft_action,\n+\t.signal_monitor = capwap_signal_monitor,\n+\t.signal_poll = capwap_signal_poll,\n+\t.send_frame = capwap_send_frame,\n+\t.shared_freq = wpa_driver_capwap_shared_freq,\n+\t.set_param = capwap_set_param,\n+\t.get_radio_name = capwap_get_radio_name,\n+\t.add_pmkid = capwap_add_pmkid,\n+\t.remove_pmkid = capwap_remove_pmkid,\n+\t.flush_pmkid = capwap_flush_pmkid,\n+\t.set_rekey_info = capwap_set_rekey_info,\n+\t.poll_client = capwap_poll_client,\n+\t.set_p2p_powersave = capwap_set_p2p_powersave,\n+#ifdef CONFIG_TDLS\n+\t.send_tdls_mgmt = capwap_send_tdls_mgmt,\n+\t.tdls_oper = capwap_tdls_oper,\n+#endif /* CONFIG_TDLS */\n+\t.stop_ap = wpa_driver_capwap_stop_ap,\n+};\ndiff -purN hostapd-20130302/src/drivers/driver.h hostapd-20130302-linux/src/drivers/driver.h\n--- hostapd-20130302/src/drivers/driver.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/driver.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -19,6 +19,7 @@\n \n #define WPA_SUPPLICANT_DRIVER_VERSION 4\n \n+#include \"drivers/nl80211_copy.h\"\n #include \"common/defs.h\"\n \n #define HOSTAPD_CHAN_DISABLED 0x00000001\n@@ -363,6 +364,13 @@ struct wpa_driver_associate_params {\n \t */\n \tint freq;\n \n+\tint beacon_interval;\n+\tint fixed_freq;\n+\tunsigned char rates[NL80211_MAX_SUPP_RATES];\n+\tint mcast_rate;\n+\tint ht_set;\n+\tunsigned int htmode;\n+\n \t/**\n \t * bg_scan_period - Background scan period in seconds, 0 to disable\n \t * background scan, or -1 to indicate no change to default driver\n@@ -982,6 +990,8 @@ struct wpa_init_params {\n \tint use_pae_group_addr;\n \tchar **bridge;\n \tsize_t num_bridge;\n+\tchar *tap;\n+\tchar *br_name;\n \n \tu8 *own_addr; /* buffer for writing own MAC address */\n };\n@@ -1223,6 +1233,15 @@ struct wpa_driver_ops {\n \t */\n \tint (*deauthenticate)(void *priv, const u8 *addr, int reason_code);\n \n+        /**\n+         * disassociate - Benunets added for capwap\n+         */\n+        int (*disassociate)(void *priv,  const u8 *addr,\n+\t\t\tint reason_code);\n+\n+\tint (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates,\n+\t\t\tint mode);\n+\n \t/**\n \t * associate - Request driver to associate\n \t * @priv: private driver interface data\n@@ -2071,6 +2090,9 @@ struct wpa_driver_ops {\n \t */\n \tint (*probe_req_report)(void *priv, int report);\n \n+\n+\tint (*stop_ap)(void *priv);\n+\n \t/**\n \t * deinit_ap - Deinitialize AP mode\n \t * @priv: Private driver interface data\n@@ -3726,8 +3748,8 @@ union wpa_event_data {\n  * Driver wrapper code should call this function whenever an event is received\n  * from the driver.\n  */\n-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,\n-\t\t\t  union wpa_event_data *data);\n+extern void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,\n+\t\t\t\t    union wpa_event_data *data);\n \n \n /*\ndiff -purN hostapd-20130302/src/drivers/driver_madwifi.c hostapd-20130302-linux/src/drivers/driver_madwifi.c\n--- hostapd-20130302/src/drivers/driver_madwifi.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/driver_madwifi.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -453,7 +453,9 @@ wpa_driver_madwifi_set_key(const char *i\n \n \tmemset(&wk, 0, sizeof(wk));\n \twk.ik_type = cipher;\n-\twk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;\n+\twk.ik_flags = IEEE80211_KEY_RECV;\n+\tif (set_tx)\n+\t\twk.ik_flags |= IEEE80211_KEY_XMIT;\n \tif (addr == NULL || is_broadcast_ether_addr(addr)) {\n \t\tmemset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);\n \t\twk.ik_keyix = key_idx;\n@@ -465,6 +467,20 @@ wpa_driver_madwifi_set_key(const char *i\n \twk.ik_keylen = key_len;\n \tmemcpy(wk.ik_keydata, key, key_len);\n \n+#ifdef WORDS_BIGENDIAN\n+#define WPA_KEY_RSC_LEN 8\n+\t{\n+\t\tsize_t i;\n+\t\tu8 tmp[WPA_KEY_RSC_LEN];\n+\t\tos_memset(tmp, 0, sizeof(tmp));\n+\t\tfor (i = 0; i < seq_len; i++)\n+\t\t\ttmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];\n+\t\tos_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);\n+\t}\n+#else /* WORDS_BIGENDIAN */\n+\tos_memcpy(&wk.ik_keyrsc, seq, seq_len);\n+#endif /* WORDS_BIGENDIAN */\n+\n \tret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));\n \tif (ret < 0) {\n \t\twpa_printf(MSG_DEBUG, \"%s: Failed to set key (addr %s\"\ndiff -purN hostapd-20130302/src/drivers/driver_nl80211.c hostapd-20130302-linux/src/drivers/driver_nl80211.c\n--- hostapd-20130302/src/drivers/driver_nl80211.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/driver_nl80211.c\t2013-07-07 03:22:14.000000000 -0400\n@@ -10,6 +10,7 @@\n  * See README for more details.\n  */\n \n+\n #include \"includes.h\"\n #include <sys/ioctl.h>\n #include <sys/types.h>\n@@ -127,7 +128,7 @@ static struct nl_handle * nl_create_hand\n \t}\n \n \tif (genl_connect(handle)) {\n-\t\twpa_printf(MSG_ERROR, \"nl80211: Failed to connect to generic \"\n+\t\twpa_printf(MSG_DEBUG, \"nl80211: Failed to connect to generic \"\n \t\t\t   \"netlink (%s)\", dbg);\n \t\tnl80211_handle_destroy(handle);\n \t\treturn NULL;\n@@ -218,7 +219,9 @@ struct wpa_driver_nl80211_data {\n \tint if_removed;\n \tint if_disabled;\n \tint ignore_if_down_event;\n+#ifdef CONFIG_RFKILL\n \tstruct rfkill_data *rfkill;\n+#endif\n \tstruct wpa_driver_capa capa;\n \tint has_capability;\n \n@@ -897,6 +900,10 @@ static void wpa_driver_nl80211_event_rtm\n \t\treturn;\n \t}\n \n+\tif (ifi->ifi_family == AF_BRIDGE &&\n+\t    drv->nlmode != NL80211_IFTYPE_AP)\n+\t\treturn;\n+\n \twpa_printf(MSG_DEBUG, \"RTM_NEWLINK: operstate=%d ifi_flags=0x%x \"\n \t\t   \"(%s%s%s%s)\",\n \t\t   drv->operstate, ifi->ifi_flags,\n@@ -1004,6 +1011,10 @@ static void wpa_driver_nl80211_event_rtm\n \tattrlen = len;\n \tattr = (struct rtattr *) buf;\n \n+\tif (ifi->ifi_family == AF_BRIDGE &&\n+\t    drv->nlmode != NL80211_IFTYPE_AP)\n+\t\treturn;\n+\n \trta_len = RTA_ALIGN(sizeof(struct rtattr));\n \twhile (RTA_OK(attr, attrlen)) {\n \t\tif (attr->rta_type == IFLA_IFNAME) {\n@@ -2959,7 +2970,7 @@ static int wpa_driver_nl80211_init_nl(st\n \treturn 0;\n }\n \n-\n+#ifdef CONFIG_RFKILL\n static void wpa_driver_nl80211_rfkill_blocked(void *ctx)\n {\n \twpa_printf(MSG_DEBUG, \"nl80211: RFKILL blocked\");\n@@ -2982,6 +2993,7 @@ static void wpa_driver_nl80211_rfkill_un\n \t}\n \t/* rtnetlink ifup handler will report interface as enabled */\n }\n+#endif /* CONFIG_RFKILL */\n \n \n static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv)\n@@ -3110,7 +3122,9 @@ static void * wpa_driver_nl80211_init(vo\n \t\t\t\t      void *global_priv)\n {\n \tstruct wpa_driver_nl80211_data *drv;\n+#ifdef CONFIG_RFKILL\n \tstruct rfkill_config *rcfg;\n+#endif\n \tstruct i802_bss *bss;\n \n \tif (global_priv == NULL)\n@@ -3129,6 +3143,12 @@ static void * wpa_driver_nl80211_init(vo\n \tdrv->monitor_sock = -1;\n \tdrv->eapol_tx_sock = -1;\n \tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n+\tdrv->nlmode = NL80211_IFTYPE_STATION;\n+\n+#ifdef HOSTAPD\n+\tdrv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);\n+\tdrv->if_indices = drv->default_if_indices;\n+#endif\n \n \tif (wpa_driver_nl80211_init_nl(drv)) {\n \t\tos_free(drv);\n@@ -3140,6 +3160,7 @@ static void * wpa_driver_nl80211_init(vo\n \n \tnl80211_get_phy_name(drv);\n \n+#ifdef CONFIG_RFKILL\n \trcfg = os_zalloc(sizeof(*rcfg));\n \tif (rcfg == NULL)\n \t\tgoto failed;\n@@ -3152,6 +3173,7 @@ static void * wpa_driver_nl80211_init(vo\n \t\twpa_printf(MSG_DEBUG, \"nl80211: RFKILL status not available\");\n \t\tos_free(rcfg);\n \t}\n+#endif /* CONFIG_RFKILL */\n \n \tif (wpa_driver_nl80211_finish_drv_init(drv))\n \t\tgoto failed;\n@@ -3441,22 +3463,19 @@ static void nl80211_mgmt_unsubscribe(str\n }\n \n \n+#ifdef CONFIG_RFKILL\n static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)\n {\n \twpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);\n }\n-\n+#endif /* CONFIG_RFKILL */\n \n static int\n-wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)\n+wpa_driver_nl80211_finish_drv_init_sta(struct wpa_driver_nl80211_data *drv,\n+\t\t\t\t       int *send_rfkill_event)\n {\n \tstruct i802_bss *bss = &drv->first_bss;\n-\tint send_rfkill_event = 0;\n-\n-\tdrv->ifindex = if_nametoindex(bss->ifname);\n-\tdrv->first_bss.ifindex = drv->ifindex;\n \n-#ifndef HOSTAPD\n \t/*\n \t * Make sure the interface starts up in station mode unless this is a\n \t * dynamically added interface (e.g., P2P) that was already configured\n@@ -3470,13 +3489,16 @@ wpa_driver_nl80211_finish_drv_init(struc\n \t}\n \n \tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {\n+#ifdef CONFIG_RFKILL\n \t\tif (rfkill_is_blocked(drv->rfkill)) {\n \t\t\twpa_printf(MSG_DEBUG, \"nl80211: Could not yet enable \"\n \t\t\t\t   \"interface '%s' due to rfkill\",\n \t\t\t\t   bss->ifname);\n \t\t\tdrv->if_disabled = 1;\n-\t\t\tsend_rfkill_event = 1;\n-\t\t} else {\n+\t\t\t*send_rfkill_event = 1;\n+\t\t} else\n+#endif\n+\t\t{\n \t\t\twpa_printf(MSG_ERROR, \"nl80211: Could not set \"\n \t\t\t\t   \"interface '%s' UP\", bss->ifname);\n \t\t\treturn -1;\n@@ -3485,7 +3507,19 @@ wpa_driver_nl80211_finish_drv_init(struc\n \n \tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,\n \t\t\t       1, IF_OPER_DORMANT);\n-#endif /* HOSTAPD */\n+}\n+\n+static int\n+wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)\n+{\n+\tstruct i802_bss *bss = &drv->first_bss;\n+\tint send_rfkill_event = 0;\n+\n+\tdrv->ifindex = if_nametoindex(bss->ifname);\n+\tdrv->first_bss.ifindex = drv->ifindex;\n+\n+\tif (drv->nlmode == NL80211_IFTYPE_STATION)\n+\t\twpa_driver_nl80211_finish_drv_init_sta(drv, &send_rfkill_event);\n \n \tif (wpa_driver_nl80211_capa(drv))\n \t\treturn -1;\n@@ -3495,24 +3529,28 @@ wpa_driver_nl80211_finish_drv_init(struc\n \t\treturn -1;\n \n \tif (send_rfkill_event) {\n+#ifdef CONFIG_RFKILL\n \t\teloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,\n \t\t\t\t       drv, drv->ctx);\n+#endif\n \t}\n \n \treturn 0;\n }\n \n \n-static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)\n+static int wpa_driver_nl80211_del_bss_beacon(struct i802_bss *bss)\n {\n+\tstruct wpa_driver_nl80211_data *drv = bss->drv;\n \tstruct nl_msg *msg;\n \n+\tbss->beacon_set = 0;\n \tmsg = nlmsg_alloc();\n \tif (!msg)\n \t\treturn -ENOMEM;\n \n \tnl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);\n-\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n+\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n \n \treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n  nla_put_failure:\n@@ -3520,6 +3558,21 @@ static int wpa_driver_nl80211_del_beacon\n \treturn -ENOBUFS;\n }\n \n+static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)\n+{\n+\tstruct i802_bss *bss;\n+\n+\tfor (bss = &drv->first_bss; bss; bss = bss->next)\n+\t\twpa_driver_nl80211_del_bss_beacon(bss);\n+\n+\treturn 0;\n+}\n+\n+static int wpa_driver_nl80211_stop_ap(void *priv)\n+{\n+\tstruct i802_bss *bss = priv;\n+\treturn wpa_driver_nl80211_del_beacon(bss->drv);\n+}\n \n /**\n  * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface\n@@ -3582,7 +3635,9 @@ static void wpa_driver_nl80211_deinit(st\n \n \tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,\n \t\t\t       IF_OPER_UP);\n+#ifdef CONFIG_RFKILL\n \trfkill_deinit(drv->rfkill);\n+#endif\n \n \teloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);\n \n@@ -6752,7 +6807,7 @@ static int wpa_driver_nl80211_ibss(struc\n \t\t\t\t   struct wpa_driver_associate_params *params)\n {\n \tstruct nl_msg *msg;\n-\tint ret = -1;\n+\tint ret = -1, i;\n \tint count = 0;\n \n \twpa_printf(MSG_DEBUG, \"nl80211: Join IBSS (ifindex=%d)\", drv->ifindex);\n@@ -6785,6 +6840,53 @@ retry:\n \twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n \tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n \n+\tif (params->fixed_freq) {\n+\t\twpa_printf(MSG_DEBUG, \"  * fixed_freq\");\n+\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_FREQ_FIXED);\n+\t}\n+\n+\tif (params->beacon_interval > 0) {\n+\t\twpa_printf(MSG_DEBUG, \"  * beacon_interval=%d\",\n+\t\t\t   params->beacon_interval);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL,\n+\t\t\t    params->beacon_interval);\n+\t}\n+\n+\tif (params->rates[0] > 0) {\n+\t\twpa_printf(MSG_DEBUG, \"  * basic_rates:\");\n+\t\ti = 0;\n+\t\twhile (i < NL80211_MAX_SUPP_RATES &&\n+\t\t       params->rates[i] > 0) {\n+\t\t\twpa_printf(MSG_DEBUG, \"    %.1f\",\n+\t\t\t\t   (double)params->rates[i] / 2);\n+\t\t\ti++;\n+\t\t}\n+\t\tNLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, i,\n+\t\t\tparams->rates);\n+\t}\n+\n+\tif (params->mcast_rate > 0) {\n+\t\twpa_printf(MSG_DEBUG, \"  * mcast_rates=%.1f\",\n+\t\t\t   (double)params->mcast_rate / 10);\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate);\n+\t}\n+\n+\tif (params->ht_set) {\n+\t\tswitch(params->htmode) {\n+\t\t\tcase NL80211_CHAN_HT20:\n+\t\t\t\twpa_printf(MSG_DEBUG, \"  * ht=HT20\");\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_CHAN_HT40PLUS:\n+\t\t\t\twpa_printf(MSG_DEBUG, \"  * ht=HT40+\");\n+\t\t\t\tbreak;\n+\t\t\tcase NL80211_CHAN_HT40MINUS:\n+\t\t\t\twpa_printf(MSG_DEBUG, \"  * ht=HT40-\");\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,\n+\t\t\t    params->htmode);\n+\t}\n+\n \tret = nl80211_set_conn_keys(params, msg);\n \tif (ret)\n \t\tgoto nla_put_failure;\n@@ -7292,8 +7394,6 @@ static int wpa_driver_nl80211_set_mode(s\n \t\t\tret = nl80211_set_mode(drv, drv->ifindex, nlmode);\n \t\t\tif (ret == -EACCES)\n \t\t\t\tbreak;\n-\t\t\tres = linux_set_iface_flags(drv->global->ioctl_sock,\n-\t\t\t\t\t\t    bss->ifname, 1);\n \t\t\tif (res && !ret)\n \t\t\t\tret = -1;\n \t\t\telse if (ret != -EBUSY)\n@@ -7309,6 +7409,7 @@ static int wpa_driver_nl80211_set_mode(s\n \t\t\t   \"interface is down\");\n \t\tdrv->nlmode = nlmode;\n \t\tdrv->ignore_if_down_event = 1;\n+\t\tlinux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);\n \t}\n \n done:\n@@ -8013,8 +8114,6 @@ static void *i802_init(struct hostapd_da\n \t\tbr_ifindex = 0;\n \t}\n \n-\tdrv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);\n-\tdrv->if_indices = drv->default_if_indices;\n \tfor (i = 0; i < params->num_bridge; i++) {\n \t\tif (params->bridge[i]) {\n \t\t\tifindex = if_nametoindex(params->bridge[i]);\n@@ -9512,4 +9611,5 @@ const struct wpa_driver_ops wpa_driver_n\n \t.send_tdls_mgmt = nl80211_send_tdls_mgmt,\n \t.tdls_oper = nl80211_tdls_oper,\n #endif /* CONFIG_TDLS */\n+\t.stop_ap = wpa_driver_nl80211_stop_ap,\n };\ndiff -purN hostapd-20130302/src/drivers/drivers.c hostapd-20130302-linux/src/drivers/drivers.c\n--- hostapd-20130302/src/drivers/drivers.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/drivers.c\t2013-07-06 06:05:42.000000000 -0400\n@@ -7,7 +7,11 @@\n  */\n \n #include \"includes.h\"\n+#include \"common.h\"\n+#include \"driver.h\"\n \n+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,\n+\t\t\t     union wpa_event_data *data);\n \n #ifdef CONFIG_DRIVER_WEXT\n extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */\n@@ -15,6 +19,9 @@ extern struct wpa_driver_ops wpa_driver_\n #ifdef CONFIG_DRIVER_NL80211\n extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */\n #endif /* CONFIG_DRIVER_NL80211 */\n+#ifdef CONFIG_DRIVER_CAPWAP\n+extern struct wpa_driver_ops wpa_driver_capwap_ops; /* benunets capwap driver */\n+#endif\n #ifdef CONFIG_DRIVER_HOSTAP\n extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */\n #endif /* CONFIG_DRIVER_HOSTAP */\n@@ -56,6 +63,9 @@ struct wpa_driver_ops *wpa_drivers[] =\n #ifdef CONFIG_DRIVER_NL80211\n \t&wpa_driver_nl80211_ops,\n #endif /* CONFIG_DRIVER_NL80211 */\n+#ifdef CONFIG_DRIVER_CAPWAP\n+\t&wpa_driver_capwap_ops, /* benunets capwap driver */\n+#endif\n #ifdef CONFIG_DRIVER_HOSTAP\n \t&wpa_driver_hostap_ops,\n #endif /* CONFIG_DRIVER_HOSTAP */\ndiff -purN hostapd-20130302/src/drivers/drivers.c.orig hostapd-20130302-linux/src/drivers/drivers.c.orig\n--- hostapd-20130302/src/drivers/drivers.c.orig\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/drivers.c.orig\t2013-07-04 11:17:51.000000000 -0400\n@@ -0,0 +1,100 @@\n+/*\n+ * Driver interface list\n+ * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>\n+ *\n+ * This software may be distributed under the terms of the BSD license.\n+ * See README for more details.\n+ */\n+\n+#include \"includes.h\"\n+#include \"common.h\"\n+#include \"driver.h\"\n+\n+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,\n+\t\t\t     union wpa_event_data *data);\n+\n+#ifdef CONFIG_DRIVER_WEXT\n+extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */\n+#endif /* CONFIG_DRIVER_WEXT */\n+#ifdef CONFIG_DRIVER_NL80211\n+extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */\n+#endif /* CONFIG_DRIVER_NL80211 */\n+#ifdef CONFIG_DRIVER_CAPWAP_WTP\n+extern struct wpa_driver_ops wpa_driver_capwap_wtp_ops; /* benunets capwap driver */\n+#endif\n+#ifdef CONFIG_DRIVER_HOSTAP\n+extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */\n+#endif /* CONFIG_DRIVER_HOSTAP */\n+#ifdef CONFIG_DRIVER_MADWIFI\n+extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */\n+#endif /* CONFIG_DRIVER_MADWIFI */\n+#ifdef CONFIG_DRIVER_BSD\n+extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */\n+#endif /* CONFIG_DRIVER_BSD */\n+#ifdef CONFIG_DRIVER_OPENBSD\n+extern struct wpa_driver_ops wpa_driver_openbsd_ops; /* driver_openbsd.c */\n+#endif /* CONFIG_DRIVER_OPENBSD */\n+#ifdef CONFIG_DRIVER_NDIS\n+extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */\n+#endif /* CONFIG_DRIVER_NDIS */\n+#ifdef CONFIG_DRIVER_WIRED\n+extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */\n+#endif /* CONFIG_DRIVER_WIRED */\n+#ifdef CONFIG_DRIVER_TEST\n+extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */\n+#endif /* CONFIG_DRIVER_TEST */\n+#ifdef CONFIG_DRIVER_ROBOSWITCH\n+/* driver_roboswitch.c */\n+extern struct wpa_driver_ops wpa_driver_roboswitch_ops;\n+#endif /* CONFIG_DRIVER_ROBOSWITCH */\n+#ifdef CONFIG_DRIVER_ATHEROS\n+extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */\n+#endif /* CONFIG_DRIVER_ATHEROS */\n+#ifdef CONFIG_DRIVER_NONE\n+extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */\n+#endif /* CONFIG_DRIVER_NONE */\n+\n+\n+struct wpa_driver_ops *wpa_drivers[] =\n+{\n+#ifdef CONFIG_DRIVER_WEXT\n+\t&wpa_driver_wext_ops,\n+#endif /* CONFIG_DRIVER_WEXT */\n+#ifdef CONFIG_DRIVER_NL80211\n+\t&wpa_driver_nl80211_ops,\n+#endif /* CONFIG_DRIVER_NL80211 */\n+#ifdef CONFIG_DRIVER_CAPWAP_WTP\n+\t&wpa_driver_capwap_wtp_ops, /* benunets capwap driver */\n+#endif\n+#ifdef CONFIG_DRIVER_HOSTAP\n+\t&wpa_driver_hostap_ops,\n+#endif /* CONFIG_DRIVER_HOSTAP */\n+#ifdef CONFIG_DRIVER_MADWIFI\n+\t&wpa_driver_madwifi_ops,\n+#endif /* CONFIG_DRIVER_MADWIFI */\n+#ifdef CONFIG_DRIVER_BSD\n+\t&wpa_driver_bsd_ops,\n+#endif /* CONFIG_DRIVER_BSD */\n+#ifdef CONFIG_DRIVER_OPENBSD\n+\t&wpa_driver_openbsd_ops,\n+#endif /* CONFIG_DRIVER_OPENBSD */\n+#ifdef CONFIG_DRIVER_NDIS\n+\t&wpa_driver_ndis_ops,\n+#endif /* CONFIG_DRIVER_NDIS */\n+#ifdef CONFIG_DRIVER_WIRED\n+\t&wpa_driver_wired_ops,\n+#endif /* CONFIG_DRIVER_WIRED */\n+#ifdef CONFIG_DRIVER_TEST\n+\t&wpa_driver_test_ops,\n+#endif /* CONFIG_DRIVER_TEST */\n+#ifdef CONFIG_DRIVER_ROBOSWITCH\n+\t&wpa_driver_roboswitch_ops,\n+#endif /* CONFIG_DRIVER_ROBOSWITCH */\n+#ifdef CONFIG_DRIVER_ATHEROS\n+\t&wpa_driver_atheros_ops,\n+#endif /* CONFIG_DRIVER_ATHEROS */\n+#ifdef CONFIG_DRIVER_NONE\n+\t&wpa_driver_none_ops,\n+#endif /* CONFIG_DRIVER_NONE */\n+\tNULL\n+};\ndiff -purN hostapd-20130302/src/drivers/drivers.mak hostapd-20130302-linux/src/drivers/drivers.mak\n--- hostapd-20130302/src/drivers/drivers.mak\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/drivers.mak\t2013-07-06 06:06:37.000000000 -0400\n@@ -20,7 +20,7 @@ endif\n ifdef CONFIG_DRIVER_NL80211\n DRV_CFLAGS += -DCONFIG_DRIVER_NL80211\n DRV_OBJS += ../src/drivers/driver_nl80211.o\n-DRV_OBJS += ../src/utils/radiotap.o\n+NEED_RADIOTAP=y\n NEED_SME=y\n NEED_AP_MLME=y\n NEED_NETLINK=y\n@@ -138,6 +138,47 @@ DRV_WPA_OBJS += ../src/drivers/driver_we\n NEED_RFKILL=y\n endif\n \n+ifdef CONFIG_DRIVER_CAPWAP\n+DRV_CFLAGS += -DCONFIG_DRIVER_CAPWAP\n+DRV_OBJS += ../src/drivers/driver_capwap.o\n+NEED_RADIOTAP=y\n+NEED_SME=y\n+NEED_AP_MLME=y\n+NEED_FAKE_NETLINK=y\n+NEED_LINUX_FAKE_IOCTL=y\n+NEED_CAPWAP_MGMT_FRAME_AC=y\n+NEED_CAPWAP_IPC_AC=y\n+NEED_RFKILL=y\n+\n+ifdef CONFIG_LIBNL32\n+  DRV_LIBS += -lnl-3\n+  DRV_LIBS += -lnl-genl-3\n+  DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3\n+else\n+  ifdef CONFIG_LIBNL_TINY\n+    DRV_LIBS += -lnl-tiny\n+  else\n+    DRV_LIBS += -lnl\n+  endif\n+\n+   ifdef CONFIG_LIBNL20\n+    DRV_LIBS += -lnl-genl\n+    DRV_CFLAGS += -DCONFIG_LIBNL20\n+  endif\n+endif\n+ifdef NEED_FAKE_NETLINK\n+DRV_OBJS += ../src/drivers/netlink_fake.o\n+endif\n+\n+ifdef NEED_LINUX_FAKE_IOCTL\n+DRV_OBJS += ../src/drivers/linux_ioctl_fake.o\n+endif\n+endif\n+\n+ifdef NEED_RADIOTAP\n+DRV_OBJS += ../src/utils/radiotap.o\n+endif\n+\n ifdef NEED_NETLINK\n DRV_OBJS += ../src/drivers/netlink.o\n endif\n@@ -150,6 +191,26 @@ ifdef NEED_RFKILL\n DRV_OBJS += ../src/drivers/rfkill.o\n endif\n \n+ifdef NEED_CAPWAP_MGMT_FRAME_WTP\n+DRV_OBJS += ../src/capwap/capwap_mgmt_frame_wtp.o\n+endif\n+\n+ifdef NEED_CAPWAP_MGMT_FRAME_AC\n+DRV_OBJS += ../src/capwap/capwap_mgmt_frame_ac.o\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_WTP\n+DRV_OBJS += ../src/capwap/ipc_capwap_wtp.o\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_AC\n+DRV_OBJS += ../src/capwap/ipc_capwap_ac.o\n+endif\n+\n+ifdef NEED_SWITCH_8023\n+DRV_OBJS += ../src/capwap/switch_8023_80211.o\n+endif\n+\n ifdef CONFIG_VLAN_NETLINK\n ifdef CONFIG_FULL_DYNAMIC_VLAN\n ifdef CONFIG_LIBNL32\ndiff -purN hostapd-20130302/src/drivers/drivers.mk hostapd-20130302-linux/src/drivers/drivers.mk\n--- hostapd-20130302/src/drivers/drivers.mk\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/drivers.mk\t2013-07-06 06:06:37.000000000 -0400\n@@ -18,9 +18,9 @@ DRV_OBJS += src/drivers/driver_wired.c\n endif\n \n ifdef CONFIG_DRIVER_NL80211\n-DRV_CFLAGS += -DCONFIG_DRIVER_NL80211\n+DRV_CFLAGS += -I/usr/include -DCONFIG_DRIVER_NL80211 -D_GNU_SOURCE \n DRV_OBJS += src/drivers/driver_nl80211.c\n-DRV_OBJS += src/utils/radiotap.c\n+NEED_RADIOTAP=y\n NEED_SME=y\n NEED_AP_MLME=y\n NEED_NETLINK=y\n@@ -45,6 +45,74 @@ else\n endif\n endif\n \n+ifdef CONFIG_DRIVER_CAPWAP\n+DRV_CFLAGS += -DCONFIG_DRIVER_CAPWAP\n+DRV_OBJS += src/drivers/driver_capwap.c\n+NEED_RADIOTAP=y\n+NEED_SME=y\n+NEED_AP_MLME=y\n+NEED_FAKE_NETLINK=y\n+NEED_LINUX_FAKE_IOCTL=y\n+NEED_CAPWAP_MGMT_FRAME_AC=y\n+NEED_CAPWAP_IPC_AC=y\n+NEED_RFKILL=y\n+ifdef CONFIG_LIBNL32\n+  DRV_LIBS += -lnl-3\n+  DRV_LIBS += -lnl-genl-3\n+  DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3\n+else\n+  ifdef CONFIG_LIBNL_TINY\n+    DRV_LIBS += -lnl-tiny\n+  else\n+    DRV_LIBS += -lnl\n+  endif\n+\n+  ifdef CONFIG_LIBNL20\n+    DRV_LIBS += -lnl-genl\n+    DRV_CFLAGS += -DCONFIG_LIBNL20\n+  endif\n+endif\n+ifdef NEED_RADIOTAP\n+DRV_OBJS += src/utils/radiotap.c\n+endif\n+\n+ifdef NEED_NETLINK\n+DRV_OBJS += src/drivers/netlink.c\n+endif\n+\n+ifdef NEED_FAKE_NETLINK\n+DRV_OBJS += src/drivers/netlink_fake.c\n+endif\n+\n+ifdef NEED_LINUX_IOCTL\n+DRV_OBJS += src/drivers/linux_ioctl.c\n+endif\n+\n+ifdef NEED_LINUX_FAKE_IOCTL\n+DRV_OBJS += src/drivers/linux_ioctl_fake.c\n+endif\n+\n+ifdef NEED_RFKILL\n+DRV_OBJS += src/drivers/rfkill.c\n+endif\n+\n+ifdef NEED_CAPWAP_MGMT_FRAME_WTP\n+DRV_OBJS += src/capwap/capwap_mgmt_frame_wtp.c\n+endif\n+\n+ifdef NEED_CAPWAP_MGMT_FRAME_AC\n+DRV_OBJS += src/capwap/capwap_mgmt_frame_ac.c\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_WTP\n+DRV_OBJS += src/capwap/ipc_capwap_wtp.c\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_AC\n+DRV_OBJS += src/capwap/ipc_capwap_ac.c\n+endif\n+endif\n+\n ifdef CONFIG_DRIVER_BSD\n ifndef CONFIG_L2_PACKET\n CONFIG_L2_PACKET=freebsd\n@@ -138,6 +206,10 @@ DRV_WPA_OBJS += src/drivers/driver_wext.\n NEED_RFKILL=y\n endif\n \n+ifdef NEED_RADIOTAP\n+DRV_OBJS += src/utils/radiotap.c\n+endif\n+\n ifdef NEED_NETLINK\n DRV_OBJS += src/drivers/netlink.c\n endif\n@@ -150,6 +222,26 @@ ifdef NEED_RFKILL\n DRV_OBJS += src/drivers/rfkill.c\n endif\n \n+ifdef NEED_CAPWAP_MGMT_FRAME_WTP\n+DRV_OBJS += src/capwap/capwap_mgmt_frame_wtp.c\n+endif\n+\n+ifdef NEED_CAPWAP_MGMT_FRAME_AC\n+DRV_OBJS += src/capwap/capwap_mgmt_frame_ac.c\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_WTP\n+DRV_OBJS += src/capwap/ipc_capwap_wtp.c\n+endif\n+\n+ifdef NEED_CAPWAP_IPC_AC\n+DRV_OBJS += src/capwap/ipc_capwap_ac.c\n+endif\n+\n+ifdef NEED_SWITCH_8023\n+DRV_OBJS += src/capwap/switch_8023_80211.c\n+endif\n+\n ifdef CONFIG_DRIVER_CUSTOM\n DRV_CFLAGS += -DCONFIG_DRIVER_CUSTOM\n endif\ndiff -purN hostapd-20130302/src/drivers/driver_wext.c hostapd-20130302-linux/src/drivers/driver_wext.c\n--- hostapd-20130302/src/drivers/driver_wext.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/driver_wext.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -742,7 +742,7 @@ static void wpa_driver_wext_event_rtm_de\n \t}\n }\n \n-\n+#ifdef CONFIG_RFKILL\n static void wpa_driver_wext_rfkill_blocked(void *ctx)\n {\n \twpa_printf(MSG_DEBUG, \"WEXT: RFKILL blocked\");\n@@ -764,7 +764,7 @@ static void wpa_driver_wext_rfkill_unblo\n \t}\n \t/* rtnetlink ifup handler will report interface as enabled */\n }\n-\n+#endif /* CONFIG_RFKILL */\n \n static void wext_get_phy_name(struct wpa_driver_wext_data *drv)\n {\n@@ -810,7 +810,9 @@ void * wpa_driver_wext_init(void *ctx, c\n {\n \tstruct wpa_driver_wext_data *drv;\n \tstruct netlink_config *cfg;\n+#ifdef CONFIG_RFKILL\n \tstruct rfkill_config *rcfg;\n+#endif\n \tchar path[128];\n \tstruct stat buf;\n \n@@ -845,6 +847,7 @@ void * wpa_driver_wext_init(void *ctx, c\n \t\tgoto err2;\n \t}\n \n+#ifdef CONFIG_RFKILL\n \trcfg = os_zalloc(sizeof(*rcfg));\n \tif (rcfg == NULL)\n \t\tgoto err3;\n@@ -857,6 +860,7 @@ void * wpa_driver_wext_init(void *ctx, c\n \t\twpa_printf(MSG_DEBUG, \"WEXT: RFKILL status not available\");\n \t\tos_free(rcfg);\n \t}\n+#endif /* CONFIG_RFKILL */\n \n \tdrv->mlme_sock = -1;\n \n@@ -874,7 +878,9 @@ void * wpa_driver_wext_init(void *ctx, c\n \treturn drv;\n \n err3:\n+#ifdef CONFIG_RFKILL\n \trfkill_deinit(drv->rfkill);\n+#endif\n \tnetlink_deinit(drv->netlink);\n err2:\n \tclose(drv->ioctl_sock);\n@@ -884,10 +890,12 @@ err1:\n }\n \n \n+#ifdef CONFIG_RFKILL\n static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx)\n {\n \twpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);\n }\n+#endif /* CONFIG_RFKILL */\n \n \n static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)\n@@ -895,13 +903,16 @@ static int wpa_driver_wext_finish_drv_in\n \tint send_rfkill_event = 0;\n \n \tif (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {\n+#ifdef CONFIG_RFKILL\n \t\tif (rfkill_is_blocked(drv->rfkill)) {\n \t\t\twpa_printf(MSG_DEBUG, \"WEXT: Could not yet enable \"\n \t\t\t\t   \"interface '%s' due to rfkill\",\n \t\t\t\t   drv->ifname);\n \t\t\tdrv->if_disabled = 1;\n \t\t\tsend_rfkill_event = 1;\n-\t\t} else {\n+\t\t} else\n+#endif\n+\t\t{\n \t\t\twpa_printf(MSG_ERROR, \"WEXT: Could not set \"\n \t\t\t\t   \"interface '%s' UP\", drv->ifname);\n \t\t\treturn -1;\n@@ -949,8 +960,10 @@ static int wpa_driver_wext_finish_drv_in\n \t\t\t       1, IF_OPER_DORMANT);\n \n \tif (send_rfkill_event) {\n+#ifdef CONFIG_RFKILL\n \t\teloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill,\n \t\t\t\t       drv, drv->ctx);\n+#endif\n \t}\n \n \treturn 0;\n@@ -980,7 +993,9 @@ void wpa_driver_wext_deinit(void *priv)\n \n \tnetlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);\n \tnetlink_deinit(drv->netlink);\n+#ifdef CONFIG_RFKILL\n \trfkill_deinit(drv->rfkill);\n+#endif\n \n \tif (drv->mlme_sock >= 0)\n \t\teloop_unregister_read_sock(drv->mlme_sock);\ndiff -purN hostapd-20130302/src/drivers/driver_wext.h hostapd-20130302-linux/src/drivers/driver_wext.h\n--- hostapd-20130302/src/drivers/driver_wext.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/driver_wext.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -22,7 +22,9 @@ struct wpa_driver_wext_data {\n \tint ifindex2;\n \tint if_removed;\n \tint if_disabled;\n+#ifdef CONFIG_RFKILL\n \tstruct rfkill_data *rfkill;\n+#endif\n \tu8 *assoc_req_ies;\n \tsize_t assoc_req_ies_len;\n \tu8 *assoc_resp_ies;\ndiff -purN hostapd-20130302/src/drivers/linux_ioctl_fake.c hostapd-20130302-linux/src/drivers/linux_ioctl_fake.c\n--- hostapd-20130302/src/drivers/linux_ioctl_fake.c\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/linux_ioctl_fake.c\t2013-07-06 06:06:29.000000000 -0400\n@@ -0,0 +1,137 @@\n+/*\n+ * Linux ioctl helper functions for driver wrappers\n+ * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ *\n+ * Alternatively, this software may be distributed under the terms of BSD\n+ * license.\n+ *\n+ * See README and COPYING for more details.\n+ */\n+\n+\n+#include \"utils/includes.h\"\n+#include <sys/ioctl.h>\n+#include <net/if.h>\n+#include <net/if_arp.h>\n+\n+#include \"utils/common.h\"\n+#include \"linux_ioctl_fake.h\"\n+\n+\n+\n+int linux_set_fake_iface_flags(int sock, const char *ifname, int dev_up){\n+\t\n+\treturn 0;\n+}\n+\n+int linux_iface_fake_up(int sock, const char *ifname){\n+\n+\treturn 0;\n+}\n+\n+int linux_get_fake_ifhwaddr(int sock, const char *ifname, u8 *addr){\n+\n+\tint i=2;\n+\t\n+\tif(i==0){ // TP-LINK (Atheros)\n+\t\taddr[0]=0xB0;\n+\t\taddr[1]=0x48;\n+\t\taddr[2]=0x7A;\n+\t\taddr[3]=0x93;\n+\t\taddr[4]=0x90;\n+\t\taddr[5]=0xF8;\n+\t\t\n+\t}else if(i==1){// D-Link \n+\t\taddr[0]=0x28;\n+\t\taddr[1]=0x10;\n+\t\taddr[2]=0x7B;\n+\t\taddr[3]=0x44;\n+\t\taddr[4]=0xd0;\n+\t\taddr[5]=0xB1;\n+\t\t\n+\t}else if(i==2){// TP-LINK (Atheros)\n+\t\taddr[0]=0xAA;\n+\t\taddr[1]=0xBB;\n+\t\taddr[2]=0xCC;\n+\t\taddr[3]=0xDD;\n+\t\taddr[4]=0xEE;\n+\t\taddr[5]=0xFF;\n+\t\t\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int linux_set_fake_ifhwaddr(int sock, const char *ifname,  u8 *addr){\n+\n+        int i=2;\n+\n+        if(i==0){ // TP-LINK (Atheros)\n+                addr[0]=0xB0;\n+                addr[1]=0x48;\n+                addr[2]=0x7A;\n+                addr[3]=0x93;\n+                addr[4]=0x90;\n+                addr[5]=0xF8;\n+\n+        }else if(i==1){// D-Link\n+                addr[0]=0x28;\n+                addr[1]=0x10;\n+                addr[2]=0x7B;\n+                addr[3]=0x44;\n+                addr[4]=0xd0;\n+                addr[5]=0xB1;\n+\n+        }else if(i==2){// TP-LINK (Atheros)\n+                addr[0]=0xAA;\n+                addr[1]=0xBB;\n+                addr[2]=0xCC;\n+                addr[3]=0xDD;\n+                addr[4]=0xEE;\n+                addr[5]=0xFF;\n+\n+        }\n+\n+\treturn 0;\n+}\n+\n+\n+#ifndef SIOCBRADDBR\n+#define SIOCBRADDBR 0x89a0\n+#endif\n+#ifndef SIOCBRDELBR\n+#define SIOCBRDELBR 0x89a1\n+#endif\n+#ifndef SIOCBRADDIF\n+#define SIOCBRADDIF 0x89a2\n+#endif\n+#ifndef SIOCBRDELIF\n+#define SIOCBRDELIF 0x89a3\n+#endif\n+\n+\n+int linux_br_fake_add(int sock, const char *brname){\n+\treturn 0;\n+}\n+\n+int linux_br_fake_del(int sock, const char *brname){\n+\treturn 0;\n+}\n+\n+int linux_br_fake_add_if(int sock, const char *brname, const char *ifname){\n+\treturn 0;\n+}\n+\n+int linux_br_fake_del_if(int sock, const char *brname, const char *ifname){\n+\treturn 0;\n+}\n+\n+int linux_br_fake_get(char *brname, const char *ifname){\n+\treturn 0;\n+}\n+\n+\ndiff -purN hostapd-20130302/src/drivers/linux_ioctl_fake.h hostapd-20130302-linux/src/drivers/linux_ioctl_fake.h\n--- hostapd-20130302/src/drivers/linux_ioctl_fake.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/linux_ioctl_fake.h\t2013-07-06 06:06:29.000000000 -0400\n@@ -0,0 +1,28 @@\n+/*\n+ * Linux ioctl helper functions for driver wrappers\n+ * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ *\n+ * Alternatively, this software may be distributed under the terms of BSD\n+ * license.\n+ *\n+ * See README and COPYING for more details.\n+ */\n+\n+#ifndef LINUX_IOCTL_H\n+#define LINUX_IOCTL_H\n+\n+int linux_set_iface_flags(int sock, const char *ifname, int dev_up);\n+int linux_iface_up(int sock, const char *ifname);\n+int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr);\n+int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr);\n+int linux_br_add(int sock, const char *brname);\n+int linux_br_del(int sock, const char *brname);\n+int linux_br_add_if(int sock, const char *brname, const char *ifname);\n+int linux_br_del_if(int sock, const char *brname, const char *ifname);\n+int linux_br_get(char *brname, const char *ifname);\n+\n+#endif /* LINUX_IOCTL_H */\ndiff -purN hostapd-20130302/src/drivers/netlink_fake.c hostapd-20130302-linux/src/drivers/netlink_fake.c\n--- hostapd-20130302/src/drivers/netlink_fake.c\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/netlink_fake.c\t2013-07-06 06:06:29.000000000 -0400\n@@ -0,0 +1,82 @@\n+/*\n+ * Netlink helper functions for driver wrappers\n+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ *\n+ * Alternatively, this software may be distributed under the terms of BSD\n+ * license.\n+ *\n+ * See README and COPYING for more details.\n+ */\n+\n+\n+#include \"includes.h\"\n+\n+#include \"common.h\"\n+#include \"eloop.h\"\n+#include \"priv_netlink.h\"\n+#include \"netlink_fake.h\"\n+\n+\n+\n+struct netlink_data {\n+\tstruct netlink_config *cfg;\n+\tint sock;\n+};\n+\n+\n+static void netlink_receive_link(struct netlink_data *netlink,\n+\t\t\t\t void (*cb)(void *ctx, struct ifinfomsg *ifi,\n+\t\t\t\t\t    u8 *buf, size_t len),\n+\t\t\t\t struct nlmsghdr *h)\n+{\n+\t\n+\treturn;\n+}\n+\n+\n+static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx)\n+{\n+\treturn;\n+}\n+\n+\n+struct netlink_data * netlink_fake_init(struct netlink_config *cfg)\n+{\n+\n+\tstruct netlink_data *netlink;\n+\tstruct sockaddr_nl local;\n+\n+\tnetlink = os_zalloc(sizeof(*netlink));\n+\tif (netlink == NULL)\n+\t\treturn NULL;\n+\n+\tnetlink->cfg = cfg;\n+\n+\tnetlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);\n+\n+\tos_memset(&local, 0, sizeof(local));\n+\tlocal.nl_family = AF_NETLINK;\n+\tlocal.nl_groups = RTMGRP_LINK;\n+\n+\teloop_register_read_sock(netlink->sock, netlink_receive, netlink,\n+\t\t\t\t NULL);\n+\n+\treturn netlink;\n+\n+}\n+\n+\n+void netlink_fake_deinit(struct netlink_data *netlink)\n+{\n+\treturn;\n+}\n+\n+int netlink_fake_send_oper_ifla(struct netlink_data *netlink, int ifindex,\n+\t\t\t   int linkmode, int operstate){\n+\t\n+\treturn 0;\n+}\ndiff -purN hostapd-20130302/src/drivers/netlink_fake.h hostapd-20130302-linux/src/drivers/netlink_fake.h\n--- hostapd-20130302/src/drivers/netlink_fake.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/drivers/netlink_fake.h\t2013-07-07 03:48:41.000000000 -0400\n@@ -0,0 +1,34 @@\n+/*\n+ * Netlink helper functions for driver wrappers\n+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ *\n+ * Alternatively, this software may be distributed under the terms of BSD\n+ * license.\n+ *\n+ * See README and COPYING for more details.\n+ */\n+\n+#ifndef NETLINK_FAKE_H\n+#define NETLINK_FAKE_H\n+\n+struct netlink_data;\n+struct ifinfomsg;\n+\n+struct netlink_config {\n+\tvoid *ctx;\n+\tvoid (*newlink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf,\n+\t\t\t   size_t len);\n+\tvoid (*dellink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf,\n+\t\t\t   size_t len);\n+};\n+\n+struct netlink_data * netlink_fake_init(struct netlink_config *cfg);\n+void netlink_fake_deinit(struct netlink_data *netlink);\n+int netlink_fake_send_oper_ifla(struct netlink_data *netlink, int ifindex,\n+\t\t\t   int linkmode, int operstate);\n+\n+#endif /* NETLINK_H */\ndiff -purN hostapd-20130302/src/Makefile hostapd-20130302-linux/src/Makefile\n--- hostapd-20130302/src/Makefile\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/Makefile\t2013-07-06 06:04:50.000000000 -0400\n@@ -1,4 +1,4 @@\n-SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps\n+SUBDIRS=capwap ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps\n \n all:\n \tfor d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done\ndiff -purN hostapd-20130302/src/rsn_supp/wpa.c hostapd-20130302-linux/src/rsn_supp/wpa.c\n--- hostapd-20130302/src/rsn_supp/wpa.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/rsn_supp/wpa.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -1848,6 +1848,8 @@ static u32 wpa_key_mgmt_suite(struct wpa\n }\n \n \n+#ifdef CONFIG_CTRL_IFACE_MIB\n+\n #define RSN_SUITE \"%02x-%02x-%02x-%d\"\n #define RSN_SUITE_ARG(s) \\\n ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff\n@@ -1931,6 +1933,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch\n \n \treturn (int) len;\n }\n+#endif\n #endif /* CONFIG_CTRL_IFACE */\n \n \ndiff -purN hostapd-20130302/src/tls/x509v3.c hostapd-20130302-linux/src/tls/x509v3.c\n--- hostapd-20130302/src/tls/x509v3.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/tls/x509v3.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -1848,6 +1848,9 @@ int x509_certificate_chain_validate(stru\n \t\tif (chain_trusted)\n \t\t\tcontinue;\n \n+#ifdef NO_TIMESTAMP_CHECK\n+\t\tdisable_time_checks = 1;\n+#endif\n \t\tif (!disable_time_checks &&\n \t\t    ((unsigned long) now.sec <\n \t\t     (unsigned long) cert->not_before ||\ndiff -purN hostapd-20130302/src/utils/build_features.h hostapd-20130302-linux/src/utils/build_features.h\n--- hostapd-20130302/src/utils/build_features.h\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/src/utils/build_features.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -0,0 +1,17 @@\n+#ifndef BUILD_FEATURES_H\n+#define BUILD_FEATURES_H\n+\n+static inline int has_feature(const char *feat)\n+{\n+#ifdef IEEE8021X_EAPOL\n+\tif (!strcmp(feat, \"eap\"))\n+\t\treturn 1;\n+#endif\n+#ifdef IEEE80211N\n+\tif (!strcmp(feat, \"11n\"))\n+\t\treturn 1;\n+#endif\n+\treturn 0;\n+}\n+\n+#endif /* BUILD_FEATURES_H */\ndiff -purN hostapd-20130302/src/utils/eloop.h hostapd-20130302-linux/src/utils/eloop.h\n--- hostapd-20130302/src/utils/eloop.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/utils/eloop.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -17,6 +17,7 @@\n #ifndef ELOOP_H\n #define ELOOP_H\n \n+#include \"os.h\"\n /**\n  * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts\n  */\ndiff -purN hostapd-20130302/src/utils/wpa_debug.c hostapd-20130302-linux/src/utils/wpa_debug.c\n--- hostapd-20130302/src/utils/wpa_debug.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/utils/wpa_debug.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -201,7 +201,7 @@ void wpa_debug_close_linux_tracing(void)\n  *\n  * Note: New line '\\n' is added to the end of the text when printing to stdout.\n  */\n-void wpa_printf(int level, const char *fmt, ...)\n+void _wpa_printf(int level, const char *fmt, ...)\n {\n \tva_list ap;\n \n@@ -248,8 +248,8 @@ void wpa_printf(int level, const char *f\n }\n \n \n-static void _wpa_hexdump(int level, const char *title, const u8 *buf,\n-\t\t\t size_t len, int show)\n+void _wpa_hexdump(int level, const char *title, const u8 *buf,\n+\t\t  size_t len, int show)\n {\n \tsize_t i;\n \n@@ -375,20 +375,9 @@ static void _wpa_hexdump(int level, cons\n #endif /* CONFIG_ANDROID_LOG */\n }\n \n-void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)\n-{\n-\t_wpa_hexdump(level, title, buf, len, 1);\n-}\n-\n-\n-void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)\n-{\n-\t_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);\n-}\n \n-\n-static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,\n-\t\t\t       size_t len, int show)\n+void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,\n+\t\t\tsize_t len, int show)\n {\n \tsize_t i, llen;\n \tconst u8 *pos = buf;\n@@ -495,19 +484,6 @@ static void _wpa_hexdump_ascii(int level\n }\n \n \n-void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)\n-{\n-\t_wpa_hexdump_ascii(level, title, buf, len, 1);\n-}\n-\n-\n-void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,\n-\t\t\t   size_t len)\n-{\n-\t_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);\n-}\n-\n-\n #ifdef CONFIG_DEBUG_FILE\n static char *last_path = NULL;\n #endif /* CONFIG_DEBUG_FILE */\n@@ -591,7 +567,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_\n }\n \n \n-void wpa_msg(void *ctx, int level, const char *fmt, ...)\n+void _wpa_msg(void *ctx, int level, const char *fmt, ...)\n {\n \tva_list ap;\n \tchar *buf;\n@@ -625,7 +601,7 @@ void wpa_msg(void *ctx, int level, const\n }\n \n \n-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)\n+void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)\n {\n \tva_list ap;\n \tchar *buf;\ndiff -purN hostapd-20130302/src/utils/wpa_debug.h hostapd-20130302-linux/src/utils/wpa_debug.h\n--- hostapd-20130302/src/utils/wpa_debug.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/src/utils/wpa_debug.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -15,7 +15,7 @@\n  * use these for debugging purposes. */\n \n enum {\n-\tMSG_EXCESSIVE, MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR\n+\tMSG_EXCESSIVE, MSG_MSGDUMP, MSG_ERROR, MSG_INFO, MSG_WARNING, MSG_DEBUG\n };\n \n #ifdef CONFIG_NO_STDOUT_DEBUG\n@@ -43,6 +43,17 @@ int wpa_debug_open_file(const char *path\n int wpa_debug_reopen_file(void);\n void wpa_debug_close_file(void);\n \n+/* internal */\n+void _wpa_hexdump(int level, const char *title, const u8 *buf,\n+\t\t  size_t len, int show);\n+void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,\n+\t\t\tsize_t len, int show);\n+extern int wpa_debug_show_keys;\n+\n+#ifndef CONFIG_MSG_MIN_PRIORITY\n+#define CONFIG_MSG_MIN_PRIORITY 0\n+#endif\n+\n /**\n  * wpa_debug_printf_timestamp - Print timestamp for debug output\n  *\n@@ -63,9 +74,15 @@ void wpa_debug_print_timestamp(void);\n  *\n  * Note: New line '\\n' is added to the end of the text when printing to stdout.\n  */\n-void wpa_printf(int level, const char *fmt, ...)\n+void _wpa_printf(int level, const char *fmt, ...)\n PRINTF_FORMAT(2, 3);\n \n+#define wpa_printf(level, ...)\t\t\t\t\t\t\\\n+\tdo {\t\t\t\t\t\t\t\t\\\n+\t\tif (level >= CONFIG_MSG_MIN_PRIORITY)\t\t\t\\\n+\t\t\t_wpa_printf(level, __VA_ARGS__);\t\t\\\n+\t} while(0)\n+\n /**\n  * wpa_hexdump - conditional hex dump\n  * @level: priority level (MSG_*) of the message\n@@ -77,7 +94,13 @@ PRINTF_FORMAT(2, 3);\n  * output may be directed to stdout, stderr, and/or syslog based on\n  * configuration. The contents of buf is printed out has hex dump.\n  */\n-void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);\n+static inline void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)\n+{\n+\tif (level < CONFIG_MSG_MIN_PRIORITY)\n+\t\treturn;\n+\n+\t_wpa_hexdump(level, title, buf, len, 1);\n+}\n \n static inline void wpa_hexdump_buf(int level, const char *title,\n \t\t\t\t   const struct wpabuf *buf)\n@@ -99,7 +122,13 @@ static inline void wpa_hexdump_buf(int l\n  * like wpa_hexdump(), but by default, does not include secret keys (passwords,\n  * etc.) in debug output.\n  */\n-void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);\n+static inline void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)\n+{\n+\tif (level < CONFIG_MSG_MIN_PRIORITY)\n+\t\treturn;\n+\n+\t_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);\n+}\n \n static inline void wpa_hexdump_buf_key(int level, const char *title,\n \t\t\t\t       const struct wpabuf *buf)\n@@ -121,8 +150,14 @@ static inline void wpa_hexdump_buf_key(i\n  * the hex numbers and ASCII characters (for printable range) are shown. 16\n  * bytes per line will be shown.\n  */\n-void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,\n-\t\t       size_t len);\n+static inline void wpa_hexdump_ascii(int level, const char *title,\n+\t\t\t\t     const u8 *buf, size_t len)\n+{\n+\tif (level < CONFIG_MSG_MIN_PRIORITY)\n+\t\treturn;\n+\n+\t_wpa_hexdump_ascii(level, title, buf, len, 1);\n+}\n \n /**\n  * wpa_hexdump_ascii_key - conditional hex dump, hide keys\n@@ -138,8 +173,14 @@ void wpa_hexdump_ascii(int level, const\n  * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by\n  * default, does not include secret keys (passwords, etc.) in debug output.\n  */\n-void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,\n-\t\t\t   size_t len);\n+static inline void wpa_hexdump_ascii_key(int level, const char *title,\n+\t\t\t\t\t const u8 *buf, size_t len)\n+{\n+\tif (level < CONFIG_MSG_MIN_PRIORITY)\n+\t\treturn;\n+\n+\t_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);\n+}\n \n /*\n  * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce\n@@ -172,7 +213,12 @@ void wpa_hexdump_ascii_key(int level, co\n  *\n  * Note: New line '\\n' is added to the end of the text when printing to stdout.\n  */\n-void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);\n+void _wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);\n+#define wpa_msg(ctx, level, ...)\t\t\t\t\t\\\n+\tdo {\t\t\t\t\t\t\t\t\\\n+\t\tif (level >= CONFIG_MSG_MIN_PRIORITY)\t\t\t\\\n+\t\t\t_wpa_msg(ctx, level, __VA_ARGS__);\t\t\\\n+\t} while(0)\n \n /**\n  * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors\n@@ -186,8 +232,13 @@ void wpa_msg(void *ctx, int level, const\n  * attached ctrl_iface monitors. In other words, it can be used for frequent\n  * events that do not need to be sent to syslog.\n  */\n-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)\n+void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)\n PRINTF_FORMAT(3, 4);\n+#define wpa_msg_ctrl(ctx, level, ...)\t\t\t\t\t\\\n+\tdo {\t\t\t\t\t\t\t\t\\\n+\t\tif (level >= CONFIG_MSG_MIN_PRIORITY)\t\t\t\\\n+\t\t\t_wpa_msg_ctrl(ctx, level, __VA_ARGS__);\t\t\\\n+\t} while(0)\n \n typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt,\n \t\t\t\tsize_t len);\ndiff -purN hostapd-20130302/wpa_supplicant/bss.c hostapd-20130302-linux/wpa_supplicant/bss.c\n--- hostapd-20130302/wpa_supplicant/bss.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/bss.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -11,6 +11,7 @@\n #include \"utils/common.h\"\n #include \"utils/eloop.h\"\n #include \"common/ieee802_11_defs.h\"\n+#include \"common/ieee802_11_common.h\"\n #include \"drivers/driver.h\"\n #include \"wpa_supplicant_i.h\"\n #include \"config.h\"\n@@ -227,6 +228,8 @@ struct wpa_bss * wpa_bss_get(struct wpa_\n static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,\n \t\t\t     struct os_time *fetch_time)\n {\n+\tstruct ieee80211_ht_capabilities *capab;\n+\tstruct ieee802_11_elems elems;\n \tos_time_t usec;\n \n \tdst->flags = src->flags;\n@@ -239,6 +242,12 @@ static void wpa_bss_copy_res(struct wpa_\n \tdst->level = src->level;\n \tdst->tsf = src->tsf;\n \n+\tmemset(&elems, 0, sizeof(elems));\n+\tieee802_11_parse_elems((u8 *) (src + 1), src->ie_len, &elems, 0);\n+\tcapab = (struct ieee80211_ht_capabilities *) elems.ht_capabilities;\n+\tif (capab)\n+\t\tdst->ht_capab = le_to_host16(capab->ht_capabilities_info);\n+\n \tdst->last_update.sec = fetch_time->sec;\n \tdst->last_update.usec = fetch_time->usec;\n \tdst->last_update.sec -= src->age / 1000;\ndiff -purN hostapd-20130302/wpa_supplicant/bss.h hostapd-20130302-linux/wpa_supplicant/bss.h\n--- hostapd-20130302/wpa_supplicant/bss.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/bss.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -69,6 +69,8 @@ struct wpa_bss {\n \tu8 ssid[32];\n \t/** Length of SSID */\n \tsize_t ssid_len;\n+\t/** HT caapbilities */\n+\tu16 ht_capab;\n \t/** Frequency of the channel in MHz (e.g., 2412 = channel 1) */\n \tint freq;\n \t/** Beacon interval in TUs (host byte order) */\ndiff -purN hostapd-20130302/wpa_supplicant/.config hostapd-20130302-linux/wpa_supplicant/.config\n--- hostapd-20130302/wpa_supplicant/.config\t1969-12-31 19:00:00.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/.config\t2013-06-22 15:54:23.000000000 -0400\n@@ -0,0 +1,408 @@\n+# Example wpa_supplicant build time configuration\n+#\n+# This file lists the configuration options that are used when building the\n+# hostapd binary. All lines starting with # are ignored. Configuration option\n+# lines must be commented out complete, if they are not to be included, i.e.,\n+# just setting VARIABLE=n is not disabling that variable.\n+#\n+# This file is included in Makefile, so variables like CFLAGS and LIBS can also\n+# be modified from here. In most cases, these lines should use += in order not\n+# to override previous values of the variables.\n+\n+\n+# Uncomment following two lines and fix the paths if you have installed OpenSSL\n+# or GnuTLS in non-default location\n+#CFLAGS += -I/usr/local/openssl/include\n+#LIBS += -L/usr/local/openssl/lib\n+\n+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but\n+# the kerberos files are not in the default include path. Following line can be\n+# used to fix build issues on such systems (krb5.h not found).\n+#CFLAGS += -I/usr/include/kerberos\n+\n+# Example configuration for various cross-compilation platforms\n+\n+#### sveasoft (e.g., for Linksys WRT54G) ######################################\n+#CC=mipsel-uclibc-gcc\n+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc\n+#CFLAGS += -Os\n+#CPPFLAGS += -I../src/include -I../../src/router/openssl/include\n+#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl\n+###############################################################################\n+\n+#### openwrt (e.g., for Linksys WRT54G) #######################################\n+#CC=mipsel-uclibc-gcc\n+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc\n+#CFLAGS += -Os\n+#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \\\n+#\t-I../WRT54GS/release/src/include\n+#LIBS = -lssl\n+###############################################################################\n+\n+\n+# Driver interface for Host AP driver\n+CONFIG_DRIVER_HOSTAP=y\n+\n+# Driver interface for Agere driver\n+#CONFIG_DRIVER_HERMES=y\n+# Change include directories to match with the local setup\n+#CFLAGS += -I../../hcf -I../../include -I../../include/hcf\n+#CFLAGS += -I../../include/wireless\n+\n+# Driver interface for madwifi driver\n+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.\n+#CONFIG_DRIVER_MADWIFI=y\n+# Set include directory to the madwifi source tree\n+#CFLAGS += -I../../madwifi\n+\n+# Driver interface for ndiswrapper\n+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.\n+#CONFIG_DRIVER_NDISWRAPPER=y\n+\n+# Driver interface for Atmel driver\n+# CONFIG_DRIVER_ATMEL=y\n+\n+# Driver interface for old Broadcom driver\n+# Please note that the newer Broadcom driver (\"hybrid Linux driver\") supports\n+# Linux wireless extensions and does not need (or even work) with the old\n+# driver wrapper. Use CONFIG_DRIVER_WEXT=y with that driver.\n+#CONFIG_DRIVER_BROADCOM=y\n+# Example path for wlioctl.h; change to match your configuration\n+#CFLAGS += -I/opt/WRT54GS/release/src/include\n+\n+# Driver interface for Intel ipw2100/2200 driver\n+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.\n+#CONFIG_DRIVER_IPW=y\n+\n+# Driver interface for Ralink driver\n+#CONFIG_DRIVER_RALINK=y\n+\n+# Driver interface for generic Linux wireless extensions\n+CONFIG_DRIVER_WEXT=y\n+\n+# Driver interface for Linux drivers using the nl80211 kernel interface\n+CONFIG_DRIVER_NL80211=y\n+\n+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)\n+#CONFIG_DRIVER_BSD=y\n+#CFLAGS += -I/usr/local/include\n+#LIBS += -L/usr/local/lib\n+#LIBS_p += -L/usr/local/lib\n+#LIBS_c += -L/usr/local/lib\n+\n+# Driver interface for Windows NDIS\n+#CONFIG_DRIVER_NDIS=y\n+#CFLAGS += -I/usr/include/w32api/ddk\n+#LIBS += -L/usr/local/lib\n+# For native build using mingw\n+#CONFIG_NATIVE_WINDOWS=y\n+# Additional directories for cross-compilation on Linux host for mingw target\n+#CFLAGS += -I/opt/mingw/mingw32/include/ddk\n+#LIBS += -L/opt/mingw/mingw32/lib\n+#CC=mingw32-gcc\n+# By default, driver_ndis uses WinPcap for low-level operations. This can be\n+# replaced with the following option which replaces WinPcap calls with NDISUIO.\n+# However, this requires that WZC is disabled (net stop wzcsvc) before starting\n+# wpa_supplicant.\n+# CONFIG_USE_NDISUIO=y\n+\n+# Driver interface for development testing\n+#CONFIG_DRIVER_TEST=y\n+\n+# Include client MLME (management frame processing) for test driver\n+# This can be used to test MLME operations in hostapd with the test interface.\n+# space.\n+#CONFIG_CLIENT_MLME=y\n+\n+# Driver interface for wired Ethernet drivers\n+CONFIG_DRIVER_WIRED=y\n+\n+# Driver interface for the Broadcom RoboSwitch family\n+#CONFIG_DRIVER_ROBOSWITCH=y\n+\n+# Driver interface for no driver (e.g., WPS ER only)\n+#CONFIG_DRIVER_NONE=y\n+\n+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is\n+# included)\n+CONFIG_IEEE8021X_EAPOL=y\n+\n+# EAP-MD5\n+CONFIG_EAP_MD5=y\n+\n+# EAP-MSCHAPv2\n+CONFIG_EAP_MSCHAPV2=y\n+\n+# EAP-TLS\n+CONFIG_EAP_TLS=y\n+\n+# EAL-PEAP\n+CONFIG_EAP_PEAP=y\n+\n+# EAP-TTLS\n+CONFIG_EAP_TTLS=y\n+\n+# EAP-FAST\n+# Note: Default OpenSSL package does not include support for all the\n+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,\n+# the OpenSSL library must be patched (openssl-0.9.8d-tls-extensions.patch)\n+# to add the needed functions.\n+#CONFIG_EAP_FAST=y\n+\n+# EAP-GTC\n+CONFIG_EAP_GTC=y\n+\n+# EAP-OTP\n+CONFIG_EAP_OTP=y\n+\n+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)\n+#CONFIG_EAP_SIM=y\n+\n+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)\n+#CONFIG_EAP_PSK=y\n+\n+# EAP-PAX\n+#CONFIG_EAP_PAX=y\n+\n+# LEAP\n+CONFIG_EAP_LEAP=y\n+\n+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)\n+#CONFIG_EAP_AKA=y\n+\n+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).\n+# This requires CONFIG_EAP_AKA to be enabled, too.\n+#CONFIG_EAP_AKA_PRIME=y\n+\n+# Enable USIM simulator (Milenage) for EAP-AKA\n+#CONFIG_USIM_SIMULATOR=y\n+\n+# EAP-SAKE\n+#CONFIG_EAP_SAKE=y\n+\n+# EAP-GPSK\n+#CONFIG_EAP_GPSK=y\n+# Include support for optional SHA256 cipher suite in EAP-GPSK\n+#CONFIG_EAP_GPSK_SHA256=y\n+\n+# EAP-TNC and related Trusted Network Connect support (experimental)\n+#CONFIG_EAP_TNC=y\n+\n+# Wi-Fi Protected Setup (WPS)\n+CONFIG_WPS=y\n+\n+# EAP-IKEv2\n+#CONFIG_EAP_IKEV2=y\n+\n+# PKCS#12 (PFX) support (used to read private key and certificate file from\n+# a file that usually has extension .p12 or .pfx)\n+CONFIG_PKCS12=y\n+\n+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl\n+# engine.\n+CONFIG_SMARTCARD=y\n+\n+# PC/SC interface for smartcards (USIM, GSM SIM)\n+# Enable this if EAP-SIM or EAP-AKA is included\n+#CONFIG_PCSC=y\n+\n+# Development testing\n+#CONFIG_EAPOL_TEST=y\n+\n+# Select control interface backend for external programs, e.g, wpa_cli:\n+# unix = UNIX domain sockets (default for Linux/*BSD)\n+# udp = UDP sockets using localhost (127.0.0.1)\n+# named_pipe = Windows Named Pipe (default for Windows)\n+# y = use default (backwards compatibility)\n+# If this option is commented out, control interface is not included in the\n+# build.\n+CONFIG_CTRL_IFACE=y\n+\n+# Include support for GNU Readline and History Libraries in wpa_cli.\n+# When building a wpa_cli binary for distribution, please note that these\n+# libraries are licensed under GPL and as such, BSD license may not apply for\n+# the resulting binary.\n+#CONFIG_READLINE=y\n+\n+# Remove debugging code that is printing out debug message to stdout.\n+# This can be used to reduce the size of the wpa_supplicant considerably\n+# if debugging code is not needed. The size reduction can be around 35%\n+# (e.g., 90 kB).\n+#CONFIG_NO_STDOUT_DEBUG=y\n+\n+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save\n+# 35-50 kB in code size.\n+#CONFIG_NO_WPA=y\n+\n+# Remove WPA2 support. This allows WPA to be used, but removes WPA2 code to\n+# save about 1 kB in code size when building only WPA-Personal (no EAP support)\n+# or 6 kB if building for WPA-Enterprise.\n+#CONFIG_NO_WPA2=y\n+\n+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support\n+# This option can be used to reduce code size by removing support for\n+# converting ASCII passphrases into PSK. If this functionality is removed, the\n+# PSK can only be configured as the 64-octet hexstring (e.g., from\n+# wpa_passphrase). This saves about 0.5 kB in code size.\n+#CONFIG_NO_WPA_PASSPHRASE=y\n+\n+# Disable scan result processing (ap_mode=1) to save code size by about 1 kB.\n+# This can be used if ap_scan=1 mode is never enabled.\n+#CONFIG_NO_SCAN_PROCESSING=y\n+\n+# Select configuration backend:\n+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file\n+#\tpath is given on command line, not here; this option is just used to\n+#\tselect the backend that allows configuration files to be used)\n+# winreg = Windows registry (see win_example.reg for an example)\n+CONFIG_BACKEND=file\n+\n+# Remove configuration write functionality (i.e., to allow the configuration\n+# file to be updated based on runtime configuration changes). The runtime\n+# configuration can still be changed, the changes are just not going to be\n+# persistent over restarts. This option can be used to reduce code size by\n+# about 3.5 kB.\n+#CONFIG_NO_CONFIG_WRITE=y\n+\n+# Remove support for configuration blobs to reduce code size by about 1.5 kB.\n+#CONFIG_NO_CONFIG_BLOBS=y\n+\n+# Select program entry point implementation:\n+# main = UNIX/POSIX like main() function (default)\n+# main_winsvc = Windows service (read parameters from registry)\n+# main_none = Very basic example (development use only)\n+#CONFIG_MAIN=main\n+\n+# Select wrapper for operatins system and C library specific functions\n+# unix = UNIX/POSIX like systems (default)\n+# win32 = Windows systems\n+# none = Empty template\n+#CONFIG_OS=unix\n+\n+# Select event loop implementation\n+# eloop = select() loop (default)\n+# eloop_win = Windows events and WaitForMultipleObject() loop\n+# eloop_none = Empty template\n+#CONFIG_ELOOP=eloop\n+\n+# Select layer 2 packet implementation\n+# linux = Linux packet socket (default)\n+# pcap = libpcap/libdnet/WinPcap\n+# freebsd = FreeBSD libpcap\n+# winpcap = WinPcap with receive thread\n+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)\n+# none = Empty template\n+#CONFIG_L2_PACKET=linux\n+\n+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)\n+CONFIG_PEERKEY=y\n+\n+# IEEE 802.11w (management frame protection)\n+# This version is an experimental implementation based on IEEE 802.11w/D1.0\n+# draft and is subject to change since the standard has not yet been finalized.\n+# Driver support is also needed for IEEE 802.11w.\n+CONFIG_IEEE80211W=y\n+\n+# Select TLS implementation\n+# openssl = OpenSSL (default)\n+# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA)\n+# internal = Internal TLSv1 implementation (experimental)\n+# none = Empty template\n+CONFIG_TLS=internal\n+\n+# Whether to enable TLS/IA support, which is required for EAP-TTLSv1.\n+# You need CONFIG_TLS=gnutls for this to have any effect. Please note that\n+# even though the core GnuTLS library is released under LGPL, this extra\n+# library uses GPL and as such, the terms of GPL apply to the combination\n+# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not\n+# apply for distribution of the resulting binary.\n+#CONFIG_GNUTLS_EXTRA=y\n+\n+# If CONFIG_TLS=internal is used, additional library and include paths are\n+# needed for LibTomMath. Alternatively, an integrated, minimal version of\n+# LibTomMath can be used. See beginning of libtommath.c for details on benefits\n+# and drawbacks of this option.\n+CONFIG_INTERNAL_LIBTOMMATH=y\n+#ifndef CONFIG_INTERNAL_LIBTOMMATH\n+#LTM_PATH=/usr/src/libtommath-0.39\n+#CFLAGS += -I$(LTM_PATH)\n+#LIBS += -L$(LTM_PATH)\n+#LIBS_p += -L$(LTM_PATH)\n+#endif\n+# At the cost of about 4 kB of additional binary size, the internal LibTomMath\n+# can be configured to include faster routines for exptmod, sqr, and div to\n+# speed up DH and RSA calculation considerably\n+CONFIG_INTERNAL_LIBTOMMATH_FAST=y\n+\n+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.\n+# This is only for Windows builds and requires WMI-related header files and\n+# WbemUuid.Lib from Platform SDK even when building with MinGW.\n+#CONFIG_NDIS_EVENTS_INTEGRATED=y\n+#PLATFORMSDKLIB=\"/opt/Program Files/Microsoft Platform SDK/Lib\"\n+\n+# Add support for old DBus control interface\n+# (fi.epitest.hostap.WPASupplicant)\n+#CONFIG_CTRL_IFACE_DBUS=y\n+\n+# Add support for new DBus control interface\n+# (fi.w1.hostap.wpa_supplicant1)\n+#CONFIG_CTRL_IFACE_DBUS_NEW=y\n+\n+# Add introspection support for new DBus control interface\n+#CONFIG_CTRL_IFACE_DBUS_INTRO=y\n+\n+# Add support for loading EAP methods dynamically as shared libraries.\n+# When this option is enabled, each EAP method can be either included\n+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).\n+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to\n+# be loaded in the beginning of the wpa_supplicant configuration file\n+# (see load_dynamic_eap parameter in the example file) before being used in\n+# the network blocks.\n+#\n+# Note that some shared parts of EAP methods are included in the main program\n+# and in order to be able to use dynamic EAP methods using these parts, the\n+# main program must have been build with the EAP method enabled (=y or =dyn).\n+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries\n+# unless at least one of them was included in the main build to force inclusion\n+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included\n+# in the main build to be able to load these methods dynamically.\n+#\n+# Please also note that using dynamic libraries will increase the total binary\n+# size. Thus, it may not be the best option for targets that have limited\n+# amount of memory/flash.\n+#CONFIG_DYNAMIC_EAP_METHODS=y\n+\n+# IEEE Std 802.11r-2008 (Fast BSS Transition)\n+#CONFIG_IEEE80211R=y\n+\n+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)\n+#CONFIG_DEBUG_FILE=y\n+\n+# Enable privilege separation (see README 'Privilege separation' for details)\n+#CONFIG_PRIVSEP=y\n+\n+# Enable mitigation against certain attacks against TKIP by delaying Michael\n+# MIC error reports by a random amount of time between 0 and 60 seconds\n+#CONFIG_DELAYED_MIC_ERROR_REPORT=y\n+\n+# Enable tracing code for developer debugging\n+# This tracks use of memory allocations and other registrations and reports\n+# incorrect use with a backtrace of call (or allocation) location.\n+#CONFIG_WPA_TRACE=y\n+# For BSD, comment out these.\n+#LIBS += -lexecinfo\n+#LIBS_p += -lexecinfo\n+#LIBS_c += -lexecinfo\n+\n+# Use libbfd to get more details for developer debugging\n+# This enables use of libbfd to get more detailed symbols for the backtraces\n+# generated by CONFIG_WPA_TRACE=y.\n+#CONFIG_WPA_TRACE_BFD=y\n+# For BSD, comment out these.\n+#LIBS += -lbfd -liberty -lz\n+#LIBS_p += -lbfd -liberty -lz\n+#LIBS_c += -lbfd -liberty -lz\n+\n+NEED_80211_COMMON=y\n+\n+CONFIG_IBSS_RSN=y\ndiff -purN hostapd-20130302/wpa_supplicant/config.c hostapd-20130302-linux/wpa_supplicant/config.c\n--- hostapd-20130302/wpa_supplicant/config.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/config.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -14,6 +14,7 @@\n #include \"rsn_supp/wpa.h\"\n #include \"eap_peer/eap.h\"\n #include \"p2p/p2p.h\"\n+#include \"drivers/nl80211_copy.h\"\n #include \"config.h\"\n \n \n@@ -1369,6 +1370,162 @@ static char * wpa_config_write_p2p_clien\n \n #endif /* CONFIG_P2P */\n \n+static int wpa_config_parse_mcast_rate(const struct parse_data *data,\n+\t\t\t\t       struct wpa_ssid *ssid, int line,\n+\t\t\t\t       const char *value)\n+{\n+\tssid->mcast_rate = (int)(strtod(value, NULL) * 10);\n+\n+\treturn 0;\n+}\n+\n+#ifndef NO_CONFIG_WRITE\n+static char * wpa_config_write_mcast_rate(const struct parse_data *data,\n+\t\t\t\t\t  struct wpa_ssid *ssid)\n+{\n+\tchar *value;\n+\tint res;\n+\n+\tif (!ssid->mcast_rate == 0)\n+\t\treturn NULL;\n+\n+\tvalue = os_malloc(6); /* longest: 300.0 */\n+\tif (value == NULL)\n+\t\treturn NULL;\n+\tres = os_snprintf(value, 5, \"%.1f\", (double)ssid->mcast_rate / 10);\n+\tif (res < 0) {\n+\t\tos_free(value);\n+\t\treturn NULL;\n+\t}\n+\treturn value;\n+}\n+#endif /* NO_CONFIG_WRITE */\n+\n+static int wpa_config_parse_htmode(const struct parse_data *data,\n+\t\t\t\t   struct wpa_ssid *ssid, int line,\n+\t\t\t\t   const char *value)\n+{\n+\tint i;\n+\tstatic const struct {\n+\t\tconst char *name;\n+\t\tunsigned int val;\n+\t} htmap[] = {\n+\t\t{ .name = \"HT20\", .val = NL80211_CHAN_HT20, },\n+\t\t{ .name = \"HT40+\", .val = NL80211_CHAN_HT40PLUS, },\n+\t\t{ .name = \"HT40-\", .val = NL80211_CHAN_HT40MINUS, },\n+\t\t{ .name = \"NOHT\", .val = NL80211_CHAN_NO_HT, },\n+\t};\n+\tssid->ht_set = 0;;\n+\tfor (i = 0; i < 4; i++) {\n+\t\tif (strcasecmp(htmap[i].name, value) == 0) {\n+\t\t\tssid->htmode = htmap[i].val;\n+\t\t\tssid->ht_set = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+#ifndef NO_CONFIG_WRITE\n+static char * wpa_config_write_htmode(const struct parse_data *data,\n+\t\t\t\t      struct wpa_ssid *ssid)\n+{\n+\tchar *value;\n+\tint res;\n+\n+\tvalue = os_malloc(6); /* longest: HT40+ */\n+\tif (value == NULL)\n+\t\treturn NULL;\n+\n+\tswitch(ssid->htmode) {\n+\t\tcase NL80211_CHAN_HT20:\n+\t\t\tres = os_snprintf(value, 4, \"HT20\");\n+\t\t\tbreak;\n+\t\tcase NL80211_CHAN_HT40PLUS:\n+\t\t\tres = os_snprintf(value, 5, \"HT40+\");\n+\t\t\tbreak;\n+\t\tcase NL80211_CHAN_HT40MINUS:\n+\t\t\tres = os_snprintf(value, 5, \"HT40-\");\n+\t\t\tbreak;\n+\t\tcase NL80211_CHAN_NO_HT:\n+\t\t\tres = os_snprintf(value, 4, \"NOHT\");\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tos_free(value);\n+\t\t\treturn NULL;\n+\t}\n+\n+\tif (res < 0) {\n+\t\tos_free(value);\n+\t\treturn NULL;\n+\t}\n+\n+\treturn value;\n+}\n+#endif /* NO_CONFIG_WRITE */\n+\n+\n+static int wpa_config_parse_rates(const struct parse_data *data,\n+\t\t\t\t  struct wpa_ssid *ssid, int line,\n+\t\t\t\t  const char *value)\n+{\n+\tint i;\n+\tchar *pos, *r, *sptr, *end;\n+\tdouble rate;\n+\n+\tpos = (char *)value;\n+\tr = strtok_r(pos, \",\", &sptr);\n+\ti = 0;\n+\twhile (pos && i < NL80211_MAX_SUPP_RATES) {\n+\t\trate = 0.0;\n+\t\tif (r)\n+\t\t\trate = strtod(r, &end);\n+\t\tssid->rates[i] = rate * 2;\n+\t\tif (*end != '\\0' || rate * 2 != ssid->rates[i])\n+\t\t\treturn 1;\n+\n+\t\ti++;\n+\t\tr = strtok_r(NULL, \",\", &sptr);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+#ifndef NO_CONFIG_WRITE\n+static char * wpa_config_write_rates(const struct parse_data *data,\n+\t\t\t\t     struct wpa_ssid *ssid)\n+{\n+\tchar *value, *pos;\n+\tint res, i;\n+\n+\tif (ssid->rates[0] <= 0)\n+\t\treturn NULL;\n+\n+\tvalue = os_malloc(6 * NL80211_MAX_SUPP_RATES + 1);\n+\tif (value == NULL)\n+\t\treturn NULL;\n+\tpos = value;\n+\tfor (i = 0; i < NL80211_MAX_SUPP_RATES - 1; i++) {\n+\t\tres = os_snprintf(pos, 6, \"%.1f,\", (double)ssid->rates[i] / 2);\n+\t\tif (res < 0) {\n+\t\t\tos_free(value);\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tpos += res;\n+\t}\n+\tres = os_snprintf(pos, 6, \"%.1f\",\n+\t\t\t  (double)ssid->rates[NL80211_MAX_SUPP_RATES - 1] / 2);\n+\tif (res < 0) {\n+\t\tos_free(value);\n+\t\treturn NULL;\n+\t}\n+\n+\tvalue[6 * NL80211_MAX_SUPP_RATES] = '\\0';\n+\treturn value;\n+}\n+#endif /* NO_CONFIG_WRITE */\n+\n /* Helper macros for network block parser */\n \n #ifdef OFFSET\n@@ -1546,6 +1703,10 @@ static const struct parse_data ssid_fiel\n \t{ INT(ap_max_inactivity) },\n \t{ INT(dtim_period) },\n \t{ INT(beacon_int) },\n+\t{ INT_RANGE(fixed_freq, 0, 1) },\n+\t{ FUNC(rates) },\n+\t{ FUNC(mcast_rate) },\n+\t{ FUNC(htmode) },\n };\n \n #undef OFFSET\ndiff -purN hostapd-20130302/wpa_supplicant/config_ssid.h hostapd-20130302-linux/wpa_supplicant/config_ssid.h\n--- hostapd-20130302/wpa_supplicant/config_ssid.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/config_ssid.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -11,6 +11,7 @@\n \n #include \"common/defs.h\"\n #include \"eap_peer/eap_config.h\"\n+#include \"drivers/nl80211_copy.h\"\n \n #define MAX_SSID_LEN 32\n \n@@ -571,6 +572,12 @@ struct wpa_ssid {\n \t * dereferences since it may not be updated in all cases.\n \t */\n \tvoid *parent_cred;\n+\n+\tint fixed_freq;\n+\tunsigned char rates[NL80211_MAX_SUPP_RATES];\n+\tdouble mcast_rate;\n+\tint ht_set;\n+\tunsigned int htmode;\n };\n \n #endif /* CONFIG_SSID_H */\ndiff -purN hostapd-20130302/wpa_supplicant/ctrl_iface.c hostapd-20130302-linux/wpa_supplicant/ctrl_iface.c\n--- hostapd-20130302/wpa_supplicant/ctrl_iface.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/ctrl_iface.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -4933,6 +4933,7 @@ char * wpa_supplicant_ctrl_iface_process\n \t\t\treply_len = -1;\n \t} else if (os_strncmp(buf, \"NOTE \", 5) == 0) {\n \t\twpa_printf(MSG_INFO, \"NOTE: %s\", buf + 5);\n+#ifdef CONFIG_CTRL_IFACE_MIB\n \t} else if (os_strcmp(buf, \"MIB\") == 0) {\n \t\treply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);\n \t\tif (reply_len >= 0) {\n@@ -4944,6 +4945,7 @@ char * wpa_supplicant_ctrl_iface_process\n \t\t\telse\n \t\t\t\treply_len += res;\n \t\t}\n+#endif\n \t} else if (os_strncmp(buf, \"STATUS\", 6) == 0) {\n \t\treply_len = wpa_supplicant_ctrl_iface_status(\n \t\t\twpa_s, buf + 6, reply, reply_size);\n@@ -5350,6 +5352,7 @@ char * wpa_supplicant_ctrl_iface_process\n \t\treply_len = wpa_supplicant_ctrl_iface_bss(\n \t\t\twpa_s, buf + 4, reply, reply_size);\n #ifdef CONFIG_AP\n+#ifdef CONFIG_CTRL_IFACE_MIB\n \t} else if (os_strcmp(buf, \"STA-FIRST\") == 0) {\n \t\treply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);\n \t} else if (os_strncmp(buf, \"STA \", 4) == 0) {\n@@ -5358,6 +5361,7 @@ char * wpa_supplicant_ctrl_iface_process\n \t} else if (os_strncmp(buf, \"STA-NEXT \", 9) == 0) {\n \t\treply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,\n \t\t\t\t\t\t   reply_size);\n+#endif\n \t} else if (os_strncmp(buf, \"DEAUTHENTICATE \", 15) == 0) {\n \t\tif (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))\n \t\t\treply_len = -1;\ndiff -purN hostapd-20130302/wpa_supplicant/events.c hostapd-20130302-linux/wpa_supplicant/events.c\n--- hostapd-20130302/wpa_supplicant/events.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/events.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -2333,8 +2333,8 @@ static void wpa_supplicant_event_unprot_\n }\n \n \n-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,\n-\t\t\t  union wpa_event_data *data)\n+void supplicant_event(void *ctx, enum wpa_event_type event,\n+\t\t      union wpa_event_data *data)\n {\n \tstruct wpa_supplicant *wpa_s = ctx;\n \tu16 reason_code = 0;\ndiff -purN hostapd-20130302/wpa_supplicant/main.c hostapd-20130302-linux/wpa_supplicant/main.c\n--- hostapd-20130302/wpa_supplicant/main.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/main.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -12,6 +12,7 @@\n #endif /* __linux__ */\n \n #include \"common.h\"\n+#include \"build_features.h\"\n #include \"wpa_supplicant_i.h\"\n #include \"driver_i.h\"\n \n@@ -25,7 +26,7 @@ static void usage(void)\n \t       \"usage:\\n\"\n \t       \"  wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] \"\n \t       \"[-g<global ctrl>] \\\\\\n\"\n-\t       \"        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] \"\n+\t       \"        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-H<hostapd path>]\"\n \t       \"[-p<driver_param>] \\\\\\n\"\n \t       \"        [-b<br_ifname>] [-f<debug file>] [-e<entropy file>] \"\n \t       \"\\\\\\n\"\n@@ -67,6 +68,7 @@ static void usage(void)\n #endif /* CONFIG_DEBUG_LINUX_TRACING */\n \tprintf(\"  -t = include timestamp in debug messages\\n\"\n \t       \"  -h = show this help text\\n\"\n+\t\t   \"  -H = connect to a hostapd instance to manage state changes\\n\"\n \t       \"  -L = show license (BSD)\\n\"\n \t       \"  -o = override driver parameter for new interfaces\\n\"\n \t       \"  -O = override ctrl_interface parameter for new interfaces\\n\"\n@@ -155,7 +157,7 @@ int main(int argc, char *argv[])\n \n \tfor (;;) {\n \t\tc = getopt(argc, argv,\n-\t\t\t   \"b:Bc:C:D:de:f:g:hi:KLNo:O:p:P:qsTtuvW\");\n+\t\t\t   \"b:Bc:C:D:de:f:g:hH:i:KLNo:O:p:P:qsTtuv::W\");\n \t\tif (c < 0)\n \t\t\tbreak;\n \t\tswitch (c) {\n@@ -199,6 +201,9 @@ int main(int argc, char *argv[])\n \t\t\tusage();\n \t\t\texitcode = 0;\n \t\t\tgoto out;\n+\t\tcase 'H':\n+\t\t\tiface->hostapd_ctrl = optarg;\n+\t\t\tbreak;\n \t\tcase 'i':\n \t\t\tiface->ifname = optarg;\n \t\t\tbreak;\n@@ -244,8 +249,12 @@ int main(int argc, char *argv[])\n \t\t\tbreak;\n #endif /* CONFIG_DBUS */\n \t\tcase 'v':\n-\t\t\tprintf(\"%s\\n\", wpa_supplicant_version);\n-\t\t\texitcode = 0;\n+\t\t\tif (optarg) {\n+\t\t\t\texitcode = !has_feature(optarg);\n+\t\t\t} else {\n+\t\t\t\tprintf(\"%s\\n\", wpa_supplicant_version);\n+\t\t\t\texitcode = 0;\n+\t\t\t}\n \t\t\tgoto out;\n \t\tcase 'W':\n \t\t\tparams.wait_for_monitor++;\ndiff -purN hostapd-20130302/wpa_supplicant/Makefile hostapd-20130302-linux/wpa_supplicant/Makefile\n--- hostapd-20130302/wpa_supplicant/Makefile\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/Makefile\t2013-07-06 06:13:59.000000000 -0400\n@@ -13,7 +13,12 @@ PKG_CONFIG ?= pkg-config\n CFLAGS += -I../src\n CFLAGS += -I../src/utils\n \n+ifdef MULTICALL\n+CFLAGS += -DMULTICALL\n+endif\n+\n -include .config\n+-include $(if $(MULTICALL),../hostapd/.config)\n \n BINALL=wpa_supplicant wpa_cli\n \n@@ -75,6 +80,10 @@ OBJS_c = wpa_cli.o ../src/common/wpa_ctr\n OBJS_c += ../src/utils/wpa_debug.o\n OBJS_c += ../src/utils/common.o\n \n+ifdef MULTICALL\n+OBJS += ../src/common/wpa_ctrl.o\n+endif\n+\n ifndef CONFIG_OS\n ifdef CONFIG_NATIVE_WINDOWS\n CONFIG_OS=win32\n@@ -704,6 +713,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS\n CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS\n LIBS += -ldl -rdynamic\n endif\n+else\n+  ifdef MULTICALL\n+    OBJS += ../src/eap_common/eap_common.o\n+  endif\n endif\n \n ifdef CONFIG_AP\n@@ -712,9 +725,11 @@ NEED_EAP_COMMON=y\n NEED_RSN_AUTHENTICATOR=y\n CFLAGS += -DCONFIG_AP\n OBJS += ap.o\n+ifndef MULTICALL\n CFLAGS += -DCONFIG_NO_RADIUS\n CFLAGS += -DCONFIG_NO_ACCOUNTING\n CFLAGS += -DCONFIG_NO_VLAN\n+endif\n OBJS += ../src/ap/hostapd.o\n OBJS += ../src/ap/wpa_auth_glue.o\n OBJS += ../src/ap/utils.o\n@@ -739,6 +754,9 @@ ifdef CONFIG_WNM\n OBJS += ../src/ap/wnm_ap.o\n endif\n ifdef CONFIG_CTRL_IFACE\n+ifdef CONFIG_CTRL_IFACE_MIB\n+CFLAGS += -DCONFIG_CTRL_IFACE_MIB\n+endif\n OBJS += ../src/ap/ctrl_iface_ap.o\n endif\n \n@@ -769,10 +787,18 @@ endif\n ifdef CONFIG_HS20\n OBJS += ../src/ap/hs20.o\n endif\n+else\n+  ifdef MULTICALL\n+    OBJS += ../src/eap_server/eap_server.o\n+    OBJS += ../src/eap_server/eap_server_identity.o\n+    OBJS += ../src/eap_server/eap_server_methods.o\n+  endif\n endif\n \n ifdef NEED_RSN_AUTHENTICATOR\n+ifndef MULTICALL\n CFLAGS += -DCONFIG_NO_RADIUS\n+endif\n NEED_AES_WRAP=y\n OBJS += ../src/ap/wpa_auth.o\n OBJS += ../src/ap/wpa_auth_ie.o\n@@ -1521,6 +1547,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv)\n \n $(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config\n \n+wpa_supplicant_multi.a: .config $(BCHECK) $(OBJS) $(EXTRA_progs)\n+\t$(Q)$(CC) -c -o wpa_supplicant_multi.o -Dmain=wpa_supplicant_main $(CFLAGS) main.c\n+\t@$(E) \"  CC \" $<\n+\t@rm -f $@\n+\t@$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)\n+\n wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)\n \t$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)\n \t@$(E) \"  LD \" $@\n@@ -1591,6 +1623,12 @@ eap_ikev2.so: ../src/eap_peer/eap_ikev2.\n %@.service: %.service.arg.in\n \tsed -e 's|\\@BINDIR\\@|$(BINDIR)|g' $< >$@\n \n+dump_cflags:\n+\t@echo -n $(CFLAGS) \" \"\n+\n+dump_ldflags:\n+\t@echo -n $(LDFLAGS) $(LIBS) $(EXTRALIBS) \" \"\n+\n wpa_supplicant.exe: wpa_supplicant\n \tmv -f $< $@\n wpa_cli.exe: wpa_cli\ndiff -purN hostapd-20130302/wpa_supplicant/wpa_priv.c hostapd-20130302-linux/wpa_supplicant/wpa_priv.c\n--- hostapd-20130302/wpa_supplicant/wpa_priv.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/wpa_priv.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -819,8 +819,8 @@ static void wpa_priv_send_ft_response(st\n }\n \n \n-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,\n-\t\t\t  union wpa_event_data *data)\n+static void supplicant_event(void *ctx, enum wpa_event_type event,\n+\t\t\t     union wpa_event_data *data)\n {\n \tstruct wpa_priv_interface *iface = ctx;\n \n@@ -962,6 +962,7 @@ int main(int argc, char *argv[])\n \tif (os_program_init())\n \t\treturn -1;\n \n+\twpa_supplicant_event = supplicant_event;\n \twpa_priv_fd_workaround();\n \n \tfor (;;) {\ndiff -purN hostapd-20130302/wpa_supplicant/wpa_supplicant.c hostapd-20130302-linux/wpa_supplicant/wpa_supplicant.c\n--- hostapd-20130302/wpa_supplicant/wpa_supplicant.c\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/wpa_supplicant.c\t2013-07-04 11:17:51.000000000 -0400\n@@ -107,6 +107,55 @@ extern int wpa_debug_show_keys;\n extern int wpa_debug_timestamp;\n extern struct wpa_driver_ops *wpa_drivers[];\n \n+#ifdef MULTICALL\n+static int hostapd_stop(struct wpa_supplicant *wpa_s)\n+{\n+\tconst char *cmd = \"DOWN\";\n+\tchar buf[256];\n+\tint len = sizeof(buf);\n+\n+\tif (wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL) < 0) {\n+\t\twpa_printf(MSG_ERROR, \"\\nFailed to stop hostapd AP interfaces\\n\");\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)\n+{\n+\tchar *cmd = NULL;\n+\tchar buf[256];\n+\tint len = sizeof(buf);\n+\tint channel, hw_mode;\n+\tint ret;\n+\n+\tif (!bss)\n+\t\treturn;\n+\n+\tif (bss->freq < 4000) {\n+\t\thw_mode = HOSTAPD_MODE_IEEE80211G;\n+\t\tchannel = (bss->freq - 2407) / 5;\n+\t} else {\n+\t\thw_mode = HOSTAPD_MODE_IEEE80211A;\n+\t\tchannel = (bss->freq - 5000) / 5;\n+\t}\n+\n+\tif (asprintf(&cmd, \"UPDATE channel=%d sec_chan=0 hw_mode=%d ieee80211n=%d\",\n+\t\t     channel, hw_mode, !!bss->ht_capab) < 0) {\n+\t\treturn -1;\n+\t}\n+\n+\tret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);\n+\tfree(cmd);\n+\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_ERROR, \"\\nFailed to reload hostapd AP interfaces\\n\");\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+#endif\n+\n /* Configure default/group WEP keys for static WEP */\n int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)\n {\n@@ -676,8 +725,16 @@ void wpa_supplicant_set_state(struct wpa\n #endif /* CONFIG_P2P */\n \n \t\tsme_sched_obss_scan(wpa_s, 1);\n+#ifdef MULTICALL\n+\t\tif (wpa_s->hostapd)\n+\t\t\thostapd_reload(wpa_s, wpa_s->current_bss);\n+#endif\n \t} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||\n \t\t   state == WPA_ASSOCIATED) {\n+#ifdef MULTICALL\n+\t\tif (wpa_s->hostapd)\n+\t\t\thostapd_stop(wpa_s);\n+#endif\n \t\twpa_s->new_connection = 1;\n \t\twpa_drv_set_operstate(wpa_s, 0);\n #ifndef IEEE8021X_EAPOL\n@@ -1513,15 +1570,26 @@ void wpa_supplicant_associate(struct wpa\n \t\tparams.ssid_len = ssid->ssid_len;\n \t}\n \n-\tif (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&\n-\t    wpa_s->conf->ap_scan == 2) {\n-\t\tparams.bssid = ssid->bssid;\n-\t\tparams.fixed_bssid = 1;\n+\tif (ssid->mode == WPAS_MODE_IBSS) {\n+\t\tif (ssid->bssid_set && wpa_s->conf->ap_scan == 2) {\n+\t\t\tparams.bssid = ssid->bssid;\n+\t\t\tparams.fixed_bssid = 1;\n+\t\t}\n+\t\tif (ssid->frequency > 0 && params.freq == 0)\n+\t\t\t/* Initial channel for IBSS */\n+\t\t\tparams.freq = ssid->frequency;\n+\t\tparams.fixed_freq = ssid->fixed_freq;\n+\t\tparams.beacon_interval = ssid->beacon_int;\n+\t\ti = 0;\n+\t\twhile (i < NL80211_MAX_SUPP_RATES) {\n+\t\t\tparams.rates[i] = ssid->rates[i];\n+\t\t\ti++;\n+\t\t}\n+\t\tparams.mcast_rate = ssid->mcast_rate;\n+\t\tparams.ht_set = ssid->ht_set;\n+\t\tparams.htmode = ssid->htmode;\n \t}\n \n-\tif (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&\n-\t    params.freq == 0)\n-\t\tparams.freq = ssid->frequency; /* Initial channel for IBSS */\n \tparams.wpa_ie = wpa_ie;\n \tparams.wpa_ie_len = wpa_ie_len;\n \tparams.pairwise_suite = cipher_pairwise;\n@@ -2416,7 +2484,7 @@ static struct wpa_supplicant * wpa_suppl\n \tif (wpa_s == NULL)\n \t\treturn NULL;\n \twpa_s->scan_req = INITIAL_SCAN_REQ;\n-\twpa_s->scan_interval = 5;\n+\twpa_s->scan_interval = 1;\n \twpa_s->new_connection = 1;\n \twpa_s->parent = wpa_s;\n \twpa_s->sched_scanning = 0;\n@@ -2778,6 +2846,21 @@ static int wpa_supplicant_init_iface(str\n \t\tos_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,\n \t\t\t   sizeof(wpa_s->bridge_ifname));\n \t}\n+#ifdef MULTICALL\n+\tif (iface->hostapd_ctrl) {\n+\t\tchar *cmd = \"DOWN\";\n+\t\tchar buf[256];\n+\t\tint len = sizeof(buf);\n+\n+\t\twpa_s->hostapd = wpa_ctrl_open(iface->hostapd_ctrl);\n+\t\tif (!wpa_s->hostapd) {\n+\t\t\twpa_printf(MSG_ERROR, \"\\nFailed to connect to hostapd\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (hostapd_stop(wpa_s) < 0)\n+\t\t\treturn -1;\n+\t}\n+#endif\n \n \t/* RSNA Supplicant Key Management - INITIALIZE */\n \teapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);\n@@ -2972,6 +3055,9 @@ static void wpa_supplicant_deinit_iface(\n \t}\n }\n \n+extern void supplicant_event(void *ctx, enum wpa_event_type event,\n+\t\t\t     union wpa_event_data *data);\n+\n \n /**\n  * wpa_supplicant_add_iface - Add a new network interface\n@@ -3164,6 +3250,7 @@ struct wpa_global * wpa_supplicant_init(\n \twpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);\n #endif /* CONFIG_NO_WPA_MSG */\n \n+\twpa_supplicant_event = supplicant_event;\n \twpa_debug_open_file(params->wpa_debug_file_path);\n \tif (params->wpa_debug_syslog)\n \t\twpa_debug_open_syslog();\ndiff -purN hostapd-20130302/wpa_supplicant/wpa_supplicant_i.h hostapd-20130302-linux/wpa_supplicant/wpa_supplicant_i.h\n--- hostapd-20130302/wpa_supplicant/wpa_supplicant_i.h\t2013-03-04 09:34:02.000000000 -0500\n+++ hostapd-20130302-linux/wpa_supplicant/wpa_supplicant_i.h\t2013-07-04 11:17:51.000000000 -0400\n@@ -96,6 +96,8 @@ struct wpa_interface {\n \t * receiving of EAPOL frames from an additional interface.\n \t */\n \tconst char *bridge_ifname;\n+\n+\tconst char *hostapd_ctrl;\n };\n \n /**\n@@ -305,6 +307,8 @@ struct wpa_supplicant {\n #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */\n \tchar bridge_ifname[16];\n \n+\tstruct wpa_ctrl *hostapd;\n+\n \tchar *confname;\n \tstruct wpa_config *conf;\n \tint countermeasures;\n"
  },
  {
    "path": "hostapd_wrapper/hostapd2/hostapd_linux.conf",
    "content": "##### hostapd configuration file ##############################################\n# Empty lines and lines starting with # are ignored\n\n# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for\n# management frames); ath0 for madwifi\ninterface=wlan0\n\n# In case of madwifi, atheros, and nl80211 driver interfaces, an additional\n# configuration parameter, bridge, may be used to notify hostapd if the\n# interface is included in a bridge. This parameter is not used with Host AP\n# driver. If the bridge parameter is not set, the drivers will automatically\n# figure out the bridge interface (assuming sysfs is enabled and mounted to\n# /sys) and this parameter may not be needed.\n#\n# For nl80211, this parameter can be used to request the AP interface to be\n# added to the bridge automatically (brctl may refuse to do this before hostapd\n# has been started to change the interface mode). If needed, the bridge\n# interface is also created.\n#bridge=br0\n\n# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd);\n# default: hostap). nl80211 is used with all Linux mac80211 drivers.\n# Use driver=none if building hostapd as a standalone RADIUS server that does\n# not control any wireless/wired driver.\n# driver=hostap\ndriver=capwap\n\n# hostapd event logger configuration\n#\n# Two output method: syslog and stdout (only usable if not forking to\n# background).\n#\n# Module bitfield (ORed bitfield of modules that will be logged; -1 = all\n# modules):\n# bit 0 (1) = IEEE 802.11\n# bit 1 (2) = IEEE 802.1X\n# bit 2 (4) = RADIUS\n# bit 3 (8) = WPA\n# bit 4 (16) = driver interface\n# bit 5 (32) = IAPP\n# bit 6 (64) = MLME\n#\n# Levels (minimum value for logged events):\n#  0 = verbose debugging\n#  1 = debugging\n#  2 = informational messages\n#  3 = notification\n#  4 = warning\n#\nlogger_syslog=-1\nlogger_syslog_level=2\nlogger_stdout=-1\nlogger_stdout_level=2\n\n# Dump file for state information (on SIGUSR1)\ndump_file=/tmp/hostapd.dump\n\n# Interface for separate control program. If this is specified, hostapd\n# will create this directory and a UNIX domain socket for listening to requests\n# from external programs (CLI/GUI, etc.) for status information and\n# configuration. The socket file will be named based on the interface name, so\n# multiple hostapd processes/interfaces can be run at the same time if more\n# than one interface is used.\n# /var/run/hostapd is the recommended directory for sockets and by default,\n# hostapd_cli will use it when trying to connect with hostapd.\nctrl_interface=/var/run/hostapd\n\n# Access control for the control interface can be configured by setting the\n# directory to allow only members of a group to use sockets. This way, it is\n# possible to run hostapd as root (since it needs to change network\n# configuration and open raw sockets) and still allow GUI/CLI components to be\n# run as non-root users. However, since the control interface can be used to\n# change the network configuration, this access needs to be protected in many\n# cases. By default, hostapd is configured to use gid 0 (root). If you\n# want to allow non-root users to use the contron interface, add a new group\n# and change this value to match with that group. Add users that should have\n# control interface access to this group.\n#\n# This variable can be a group name or gid.\n#ctrl_interface_group=wheel\nctrl_interface_group=0\n\n\n##### IEEE 802.11 related configuration #######################################\n\n# SSID to be used in IEEE 802.11 management frames\nssid=SET_BY_LINUX_HOSTAPDCONF_FILE\n\n# Country code (ISO/IEC 3166-1). Used to set regulatory domain.\n# Set as needed to indicate country in which device is operating.\n# This can limit available channels and transmit power.\n#country_code=US\n\n# Enable IEEE 802.11d. This advertises the country_code and the set of allowed\n# channels and transmit power levels based on the regulatory limits. The\n# country_code setting must be configured with the correct country for\n# IEEE 802.11d functions.\n# (default: 0 = disabled)\n#ieee80211d=1\n\n# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,\n# Default: IEEE 802.11b\nhw_mode=b\n\n# Channel number (IEEE 802.11)\n# (default: 0, i.e., not set)\n# Please note that some drivers do not use this value from hostapd and the\n# channel will need to be configured separately with iwconfig.\nchannel=1\n\n# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)\nbeacon_int=100\n\n# DTIM (delivery traffic information message) period (range 1..255):\n# number of beacons between DTIMs (1 = every beacon includes DTIM element)\n# (default: 2)\ndtim_period=2\n\n# Maximum number of stations allowed in station table. New stations will be\n# rejected after the station table is full. IEEE 802.11 has a limit of 2007\n# different association IDs, so this number should not be larger than that.\n# (default: 2007)\nmax_num_sta=255\n\n# RTS/CTS threshold; 2347 = disabled (default); range 0..2347\n# If this field is not included in hostapd.conf, hostapd will not control\n# RTS threshold and 'iwconfig wlan# rts <val>' can be used to set it.\nrts_threshold=2347\n\n# Fragmentation threshold; 2346 = disabled (default); range 256..2346\n# If this field is not included in hostapd.conf, hostapd will not control\n# fragmentation threshold and 'iwconfig wlan# frag <val>' can be used to set\n# it.\nfragm_threshold=2346\n\n# Rate configuration\n# Default is to enable all rates supported by the hardware. This configuration\n# item allows this list be filtered so that only the listed rates will be left\n# in the list. If the list is empty, all rates are used. This list can have\n# entries that are not in the list of rates the hardware supports (such entries\n# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110.\n# If this item is present, at least one rate have to be matching with the rates\n# hardware supports.\n# default: use the most common supported rate setting for the selected\n# hw_mode (i.e., this line can be removed from configuration file in most\n# cases)\n#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540\n\n# Basic rate set configuration\n# List of rates (in 100 kbps) that are included in the basic rate set.\n# If this item is not included, usually reasonable default set is used.\n#basic_rates=10 20\n#basic_rates=10 20 55 110\n#basic_rates=60 120 240\n\n# Short Preamble\n# This parameter can be used to enable optional use of short preamble for\n# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance.\n# This applies only to IEEE 802.11b-compatible networks and this should only be\n# enabled if the local hardware supports use of short preamble. If any of the\n# associated STAs do not support short preamble, use of short preamble will be\n# disabled (and enabled when such STAs disassociate) dynamically.\n# 0 = do not allow use of short preamble (default)\n# 1 = allow use of short preamble\npreamble=1\n\n# Station MAC address -based authentication\n# Please note that this kind of access control requires a driver that uses\n# hostapd to take care of management frame processing and as such, this can be\n# used with driver=hostap or driver=nl80211, but not with driver=madwifi.\n# 0 = accept unless in deny list\n# 1 = deny unless in accept list\n# 2 = use external RADIUS server (accept/deny lists are searched first)\nmacaddr_acl=0\n\n# Accept/deny lists are read from separate files (containing list of\n# MAC addresses, one per line). Use absolute path name to make sure that the\n# files can be read on SIGHUP configuration reloads.\n#accept_mac_file=/etc/hostapd.accept\n#deny_mac_file=/etc/hostapd.deny\n\n# IEEE 802.11 specifies two authentication algorithms. hostapd can be\n# configured to allow both of these or only one. Open system authentication\n# should be used with IEEE 802.1X.\n# Bit fields of allowed authentication algorithms:\n# bit 0 = Open System Authentication\n# bit 1 = Shared Key Authentication (requires WEP)\nauth_algs=1\n\n# Send empty SSID in beacons and ignore probe request frames that do not\n# specify full SSID, i.e., require stations to know SSID.\n# default: disabled (0)\n# 1 = send empty (length=0) SSID in beacon and ignore probe request for\n#     broadcast SSID\n# 2 = clear SSID (ASCII 0), but keep the original length (this may be required\n#     with some clients that do not support empty SSID) and ignore probe\n#     requests for broadcast SSID\nignore_broadcast_ssid=0\n\n# TX queue parameters (EDCF / bursting)\n# tx_queue_<queue name>_<param>\n# queues: data0, data1, data2, data3, after_beacon, beacon\n#\t\t(data0 is the highest priority queue)\n# parameters:\n#   aifs: AIFS (default 2)\n#   cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023)\n#   cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin\n#   burst: maximum length (in milliseconds with precision of up to 0.1 ms) for\n#          bursting\n#\n# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):\n# These parameters are used by the access point when transmitting frames\n# to the clients.\n#\n# Low priority / AC_BK = background\n#tx_queue_data3_aifs=7\n#tx_queue_data3_cwmin=15\n#tx_queue_data3_cwmax=1023\n#tx_queue_data3_burst=0\n# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0\n#\n# Normal priority / AC_BE = best effort\n#tx_queue_data2_aifs=3\n#tx_queue_data2_cwmin=15\n#tx_queue_data2_cwmax=63\n#tx_queue_data2_burst=0\n# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0\n#\n# High priority / AC_VI = video\n#tx_queue_data1_aifs=1\n#tx_queue_data1_cwmin=7\n#tx_queue_data1_cwmax=15\n#tx_queue_data1_burst=3.0\n# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0\n#\n# Highest priority / AC_VO = voice\n#tx_queue_data0_aifs=1\n#tx_queue_data0_cwmin=3\n#tx_queue_data0_cwmax=7\n#tx_queue_data0_burst=1.5\n# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3\n\n# 802.1D Tag (= UP) to AC mappings\n# WMM specifies following mapping of data frames to different ACs. This mapping\n# can be configured using Linux QoS/tc and sch_pktpri.o module.\n# 802.1D Tag\t802.1D Designation\tAccess Category\tWMM Designation\n# 1\t\tBK\t\t\tAC_BK\t\tBackground\n# 2\t\t-\t\t\tAC_BK\t\tBackground\n# 0\t\tBE\t\t\tAC_BE\t\tBest Effort\n# 3\t\tEE\t\t\tAC_BE\t\tBest Effort\n# 4\t\tCL\t\t\tAC_VI\t\tVideo\n# 5\t\tVI\t\t\tAC_VI\t\tVideo\n# 6\t\tVO\t\t\tAC_VO\t\tVoice\n# 7\t\tNC\t\t\tAC_VO\t\tVoice\n# Data frames with no priority information: AC_BE\n# Management frames: AC_VO\n# PS-Poll frames: AC_BE\n\n# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):\n# for 802.11a or 802.11g networks\n# These parameters are sent to WMM clients when they associate.\n# The parameters will be used by WMM clients for frames transmitted to the\n# access point.\n#\n# note - txop_limit is in units of 32microseconds\n# note - acm is admission control mandatory flag. 0 = admission control not\n# required, 1 = mandatory\n# note - here cwMin and cmMax are in exponent form. the actual cw value used\n# will be (2^n)-1 where n is the value given here\n#\nwmm_enabled=1\n#\n# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD]\n# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver)\n#uapsd_advertisement_enabled=1\n#\n# Low priority / AC_BK = background\nwmm_ac_bk_cwmin=4\nwmm_ac_bk_cwmax=10\nwmm_ac_bk_aifs=7\nwmm_ac_bk_txop_limit=0\nwmm_ac_bk_acm=0\n# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10\n#\n# Normal priority / AC_BE = best effort\nwmm_ac_be_aifs=3\nwmm_ac_be_cwmin=4\nwmm_ac_be_cwmax=10\nwmm_ac_be_txop_limit=0\nwmm_ac_be_acm=0\n# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7\n#\n# High priority / AC_VI = video\nwmm_ac_vi_aifs=2\nwmm_ac_vi_cwmin=3\nwmm_ac_vi_cwmax=4\nwmm_ac_vi_txop_limit=94\nwmm_ac_vi_acm=0\n# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188\n#\n# Highest priority / AC_VO = voice\nwmm_ac_vo_aifs=2\nwmm_ac_vo_cwmin=2\nwmm_ac_vo_cwmax=3\nwmm_ac_vo_txop_limit=47\nwmm_ac_vo_acm=0\n# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102\n\n# Static WEP key configuration\n#\n# The key number to use when transmitting.\n# It must be between 0 and 3, and the corresponding key must be set.\n# default: not set\n#wep_default_key=0\n# The WEP keys to use.\n# A key may be a quoted string or unquoted hexadecimal digits.\n# The key length should be 5, 13, or 16 characters, or 10, 26, or 32\n# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or\n# 128-bit (152-bit) WEP is used.\n# Only the default key must be supplied; the others are optional.\n# default: not set\n#wep_key0=123456789a\n#wep_key1=\"vwxyz\"\n#wep_key2=0102030405060708090a0b0c0d\n#wep_key3=\".2.4.6.8.0.23\"\n\n# Station inactivity limit\n#\n# If a station does not send anything in ap_max_inactivity seconds, an\n# empty data frame is sent to it in order to verify whether it is\n# still in range. If this frame is not ACKed, the station will be\n# disassociated and then deauthenticated. This feature is used to\n# clear station table of old entries when the STAs move out of the\n# range.\n#\n# The station can associate again with the AP if it is still in range;\n# this inactivity poll is just used as a nicer way of verifying\n# inactivity; i.e., client will not report broken connection because\n# disassociation frame is not sent immediately without first polling\n# the STA with a data frame.\n# default: 300 (i.e., 5 minutes)\n#ap_max_inactivity=300\n\n# Disassociate stations based on excessive transmission failures or other\n# indications of connection loss. This depends on the driver capabilities and\n# may not be available with all drivers.\ndisassoc_low_ack=1\n\n# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to\n# remain asleep). Default: 65535 (no limit apart from field size)\n#max_listen_interval=100\n\n# WDS (4-address frame) mode with per-station virtual interfaces\n# (only supported with driver=nl80211)\n# This mode allows associated stations to use 4-address frames to allow layer 2\n# bridging to be used.\n#wds_sta=1\n\n# If bridge parameter is set, the WDS STA interface will be added to the same\n# bridge by default. This can be overridden with the wds_bridge parameter to\n# use a separate bridge.\n#wds_bridge=wds-br0\n\n# Client isolation can be used to prevent low-level bridging of frames between\n# associated stations in the BSS. By default, this bridging is allowed.\n#ap_isolate=1\n\n##### IEEE 802.11n related configuration ######################################\n\n# ieee80211n: Whether IEEE 802.11n (HT) is enabled\n# 0 = disabled (default)\n# 1 = enabled\n# Note: You will also need to enable WMM for full HT functionality.\n#ieee80211n=1\n\n# ht_capab: HT capabilities (list of flags)\n# LDPC coding capability: [LDPC] = supported\n# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary\n#\tchannel below the primary channel; [HT40+] = both 20 MHz and 40 MHz\n#\twith secondary channel below the primary channel\n#\t(20 MHz only if neither is set)\n#\tNote: There are limits on which channels can be used with HT40- and\n#\tHT40+. Following table shows the channels that may be available for\n#\tHT40- and HT40+ use per IEEE 802.11n Annex J:\n#\tfreq\t\tHT40-\t\tHT40+\n#\t2.4 GHz\t\t5-13\t\t1-7 (1-9 in Europe/Japan)\n#\t5 GHz\t\t40,48,56,64\t36,44,52,60\n#\t(depending on the location, not all of these channels may be available\n#\tfor use)\n#\tPlease note that 40 MHz channels may switch their primary and secondary\n#\tchannels if needed or creation of 40 MHz channel maybe rejected based\n#\ton overlapping BSSes. These changes are done automatically when hostapd\n#\tis setting up the 40 MHz channel.\n# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]\n#\t(SMPS disabled if neither is set)\n# HT-greenfield: [GF] (disabled if not set)\n# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)\n# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)\n# Tx STBC: [TX-STBC] (disabled if not set)\n# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial\n#\tstreams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC\n#\tdisabled if none of these set\n# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set)\n# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not\n#\tset)\n# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)\n# PSMP support: [PSMP] (disabled if not set)\n# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)\n#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]\n\n# Require stations to support HT PHY (reject association if they do not)\n#require_ht=1\n\n##### IEEE 802.1X-2004 related configuration ##################################\n\n# Require IEEE 802.1X authorization\nieee8021x=1\n\n# IEEE 802.1X/EAPOL version\n# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL\n# version 2. However, there are many client implementations that do not handle\n# the new version number correctly (they seem to drop the frames completely).\n# In order to make hostapd interoperate with these clients, the version number\n# can be set to the older version (1) with this configuration value.\n#eapol_version=2\n\n# Optional displayable message sent with EAP Request-Identity. The first \\0\n# in this string will be converted to ASCII-0 (nul). This can be used to\n# separate network info (comma separated list of attribute=value pairs); see,\n# e.g., RFC 4284.\n#eap_message=hello\n#eap_message=hello\\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com\n\n# WEP rekeying (disabled if key lengths are not set or are set to 0)\n# Key lengths for default/broadcast and individual/unicast keys:\n# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits)\n# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits)\n#wep_key_len_broadcast=5\n#wep_key_len_unicast=5\n# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once)\n#wep_rekey_period=300\n\n# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if\n# only broadcast keys are used)\neapol_key_index_workaround=1\n\n# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable\n# reauthentication).\n#eap_reauth_period=3600\n\n# Use PAE group address (01:80:c2:00:00:03) instead of individual target\n# address when sending EAPOL frames with driver=wired. This is the most common\n# mechanism used in wired authentication, but it also requires that the port\n# is only used by one station.\n#use_pae_group_addr=1\n\n##### Integrated EAP server ###################################################\n\n# Optionally, hostapd can be configured to use an integrated EAP server\n# to process EAP authentication locally without need for an external RADIUS\n# server. This functionality can be used both as a local authentication server\n# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices.\n\n# Use integrated EAP server instead of external RADIUS authentication\n# server. This is also needed if hostapd is configured to act as a RADIUS\n# authentication server.\neap_server=0\n\n# Path for EAP server user database\n#eap_user_file=/etc/hostapd.eap_user\n\n# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS\n#ca_cert=/etc/hostapd.ca.pem\n\n# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS\n#server_cert=/etc/hostapd.server.pem\n\n# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS\n# This may point to the same file as server_cert if both certificate and key\n# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be\n# used by commenting out server_cert and specifying the PFX file as the\n# private_key.\n#private_key=/etc/hostapd.server.prv\n\n# Passphrase for private key\n#private_key_passwd=secret passphrase\n\n# Enable CRL verification.\n# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a\n# valid CRL signed by the CA is required to be included in the ca_cert file.\n# This can be done by using PEM format for CA certificate and CRL and\n# concatenating these into one file. Whenever CRL changes, hostapd needs to be\n# restarted to take the new CRL into use.\n# 0 = do not verify CRLs (default)\n# 1 = check the CRL of the user certificate\n# 2 = check all CRLs in the certificate path\n#check_crl=1\n\n# dh_file: File path to DH/DSA parameters file (in PEM format)\n# This is an optional configuration file for setting parameters for an\n# ephemeral DH key exchange. In most cases, the default RSA authentication does\n# not use this configuration. However, it is possible setup RSA to use\n# ephemeral DH key exchange. In addition, ciphers with DSA keys always use\n# ephemeral DH keys. This can be used to achieve forward secrecy. If the file\n# is in DSA parameters format, it will be automatically converted into DH\n# params. This parameter is required if anonymous EAP-FAST is used.\n# You can generate DH parameters file with OpenSSL, e.g.,\n# \"openssl dhparam -out /etc/hostapd.dh.pem 1024\"\n#dh_file=/etc/hostapd.dh.pem\n\n# Fragment size for EAP methods\n#fragment_size=1400\n\n# Configuration data for EAP-SIM database/authentication gateway interface.\n# This is a text string in implementation specific format. The example\n# implementation in eap_sim_db.c uses this as the UNIX domain socket name for\n# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses \"unix:\"\n# prefix.\n#eap_sim_db=unix:/tmp/hlr_auc_gw.sock\n\n# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,\n# random value. It is configured as a 16-octet value in hex format. It can be\n# generated, e.g., with the following command:\n# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' '\n#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f\n\n# EAP-FAST authority identity (A-ID)\n# A-ID indicates the identity of the authority that issues PACs. The A-ID\n# should be unique across all issuing servers. In theory, this is a variable\n# length field, but due to some existing implementations requiring A-ID to be\n# 16 octets in length, it is strongly recommended to use that length for the\n# field to provid interoperability with deployed peer implementations. This\n# field is configured in hex format.\n#eap_fast_a_id=101112131415161718191a1b1c1d1e1f\n\n# EAP-FAST authority identifier information (A-ID-Info)\n# This is a user-friendly name for the A-ID. For example, the enterprise name\n# and server name in a human-readable format. This field is encoded as UTF-8.\n#eap_fast_a_id_info=test server\n\n# Enable/disable different EAP-FAST provisioning modes:\n#0 = provisioning disabled\n#1 = only anonymous provisioning allowed\n#2 = only authenticated provisioning allowed\n#3 = both provisioning modes allowed (default)\n#eap_fast_prov=3\n\n# EAP-FAST PAC-Key lifetime in seconds (hard limit)\n#pac_key_lifetime=604800\n\n# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard\n# limit). The server will generate a new PAC-Key when this number of seconds\n# (or fewer) of the lifetime remains.\n#pac_key_refresh_time=86400\n\n# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND\n# (default: 0 = disabled).\n#eap_sim_aka_result_ind=1\n\n# Trusted Network Connect (TNC)\n# If enabled, TNC validation will be required before the peer is allowed to\n# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other\n# EAP method is enabled, the peer will be allowed to connect without TNC.\n#tnc=1\n\n\n##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################\n\n# Interface to be used for IAPP broadcast packets\n#iapp_interface=eth0\n\n\n##### RADIUS client configuration #############################################\n# for IEEE 802.1X with external Authentication Server, IEEE 802.11\n# authentication with external ACL for MAC addresses, and accounting\n\n# The own IP address of the access point (used as NAS-IP-Address)\nown_ip_addr=127.0.0.1\n\n# Optional NAS-Identifier string for RADIUS messages. When used, this should be\n# a unique to the NAS within the scope of the RADIUS server. For example, a\n# fully qualified domain name can be used here.\n# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and\n# 48 octets long.\nnas_identifier=OpenWrt\n\n# RADIUS authentication server\nauth_server_addr=31.1.1.1\nauth_server_port=1812\nauth_server_shared_secret=SharedSecret\n\n# RADIUS accounting server\n#acct_server_addr=127.0.0.1\n#acct_server_port=1813\n#acct_server_shared_secret=secret\n\n# Secondary RADIUS servers; to be used if primary one does not reply to\n# RADIUS packets. These are optional and there can be more than one secondary\n# server listed.\n#auth_server_addr=127.0.0.2\n#auth_server_port=1812\n#auth_server_shared_secret=secret2\n#\n#acct_server_addr=127.0.0.2\n#acct_server_port=1813\n#acct_server_shared_secret=secret2\n\n# Retry interval for trying to return to the primary RADIUS server (in\n# seconds). RADIUS client code will automatically try to use the next server\n# when the current server is not replying to requests. If this interval is set,\n# primary server will be retried after configured amount of time even if the\n# currently used secondary server is still working.\n#radius_retry_primary_interval=600\n\n\n# Interim accounting update interval\n# If this is set (larger than 0) and acct_server is configured, hostapd will\n# send interim accounting updates every N seconds. Note: if set, this overrides\n# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this\n# value should not be configured in hostapd.conf, if RADIUS server is used to\n# control the interim interval.\n# This value should not be less 600 (10 minutes) and must not be less than\n# 60 (1 minute).\n#radius_acct_interim_interval=600\n\n# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN\n# is used for the stations. This information is parsed from following RADIUS\n# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),\n# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value\n# VLANID as a string). vlan_file option below must be configured if dynamic\n# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be\n# used to set static client MAC address to VLAN ID mapping.\n# 0 = disabled (default)\n# 1 = option; use default interface if RADIUS server does not include VLAN ID\n# 2 = required; reject authentication if RADIUS server does not include VLAN ID\n#dynamic_vlan=0\n\n# VLAN interface list for dynamic VLAN mode is read from a separate text file.\n# This list is used to map VLAN ID from the RADIUS server to a network\n# interface. Each station is bound to one interface in the same way as with\n# multiple BSSIDs or SSIDs. Each line in this text file is defining a new\n# interface and the line must include VLAN ID and interface name separated by\n# white space (space or tab).\n#vlan_file=/etc/hostapd.vlan\n\n# Interface where 802.1q tagged packets should appear when a RADIUS server is\n# used to determine which VLAN a station is on.  hostapd creates a bridge for\n# each VLAN.  Then hostapd adds a VLAN interface (associated with the interface\n# indicated by 'vlan_tagged_interface') and the appropriate wireless interface\n# to the bridge.\n#vlan_tagged_interface=eth0\n\n\n##### RADIUS authentication server configuration ##############################\n\n# hostapd can be used as a RADIUS authentication server for other hosts. This\n# requires that the integrated EAP server is also enabled and both\n# authentication services are sharing the same configuration.\n\n# File name of the RADIUS clients configuration for the RADIUS server. If this\n# commented out, RADIUS server is disabled.\n#radius_server_clients=/etc/hostapd.radius_clients\n\n# The UDP port number for the RADIUS authentication server\n#radius_server_auth_port=1812\n\n# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API)\n#radius_server_ipv6=1\n\n\n##### WPA/IEEE 802.11i configuration ##########################################\n\n# Enable WPA. Setting this variable configures the AP to require WPA (either\n# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either\n# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.\n# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),\n# RADIUS authentication server must be configured, and WPA-EAP must be included\n# in wpa_key_mgmt.\n# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)\n# and/or WPA2 (full IEEE 802.11i/RSN):\n# bit0 = WPA\n# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)\nwpa=2\n\n# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit\n# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase\n# (8..63 characters) that will be converted to PSK. This conversion uses SSID\n# so the PSK changes when ASCII passphrase is used and the SSID is changed.\n# wpa_psk (dot11RSNAConfigPSKValue)\n# wpa_passphrase (dot11RSNAConfigPSKPassPhrase)\n#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n#wpa_passphrase=secret passphrase\n\n# Optionally, WPA PSKs can be read from a separate text file (containing list\n# of (PSK,MAC address) pairs. This allows more than one PSK to be configured.\n# Use absolute path name to make sure that the files can be read on SIGHUP\n# configuration reloads.\n#wpa_psk_file=/etc/hostapd.wpa_psk\n\n# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The\n# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be\n# added to enable SHA256-based stronger algorithms.\n# (dot11RSNAConfigAuthenticationSuitesTable)\nwpa_key_mgmt=WPA-EAP\n\n# Set of accepted cipher suites (encryption algorithms) for pairwise keys\n# (unicast packets). This is a space separated list of algorithms:\n# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]\n# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]\n# Group cipher suite (encryption algorithm for broadcast and multicast frames)\n# is automatically selected based on this configuration. If only CCMP is\n# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,\n# TKIP will be used as the group cipher.\n# (dot11RSNAConfigPairwiseCiphersTable)\n# Pairwise cipher for WPA (v1) (default: TKIP)\nwpa_pairwise=CCMP\n# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)\n#rsn_pairwise=CCMP\n\n# Time interval for rekeying GTK (broadcast/multicast encryption keys) in\n# seconds. (dot11RSNAConfigGroupRekeyTime)\n#wpa_group_rekey=600\n\n# Rekey GTK when any STA that possesses the current GTK is leaving the BSS.\n# (dot11RSNAConfigGroupRekeyStrict)\n#wpa_strict_rekey=1\n\n# Time interval for rekeying GMK (master key used internally to generate GTKs\n# (in seconds).\n#wpa_gmk_rekey=86400\n\n# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of\n# PTK to mitigate some attacks against TKIP deficiencies.\n#wpa_ptk_rekey=600\n\n# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up\n# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN\n# authentication and key handshake before actually associating with a new AP.\n# (dot11RSNAPreauthenticationEnabled)\n#rsn_preauth=1\n#\n# Space separated list of interfaces from which pre-authentication frames are\n# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all\n# interface that are used for connections to other APs. This could include\n# wired interfaces and WDS links. The normal wireless data interface towards\n# associated stations (e.g., wlan0) should not be added, since\n# pre-authentication is only used with APs other than the currently associated\n# one.\n#rsn_preauth_interfaces=eth0\n\n# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is\n# allowed. This is only used with RSN/WPA2.\n# 0 = disabled (default)\n# 1 = enabled\n#peerkey=1\n\n# ieee80211w: Whether management frame protection (MFP) is enabled\n# 0 = disabled (default)\n# 1 = optional\n# 2 = required\n#ieee80211w=0\n\n# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)\n# (maximum time to wait for a SA Query response)\n# dot11AssociationSAQueryMaximumTimeout, 1...4294967295\n#assoc_sa_query_max_timeout=1000\n\n# Association SA Query retry timeout (in TU = 1.024 ms; for MFP)\n# (time between two subsequent SA Query requests)\n# dot11AssociationSAQueryRetryTimeout, 1...4294967295\n#assoc_sa_query_retry_timeout=201\n\n# disable_pmksa_caching: Disable PMKSA caching\n# This parameter can be used to disable caching of PMKSA created through EAP\n# authentication. RSN preauthentication may still end up using PMKSA caching if\n# it is enabled (rsn_preauth=1).\n# 0 = PMKSA caching enabled (default)\n# 1 = PMKSA caching disabled\ndisable_pmksa_caching=0\n\n# okc: Opportunistic Key Caching (aka Proactive Key Caching)\n# Allow PMK cache to be shared opportunistically among configured interfaces\n# and BSSes (i.e., all configurations within a single hostapd process).\n# 0 = disabled (default)\n# 1 = enabled\nokc=0\n\n\n##### IEEE 802.11r configuration ##############################################\n\n# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)\n# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the\n# same SSID) between which a STA can use Fast BSS Transition.\n# 2-octet identifier as a hex string.\n#mobility_domain=a1b2\n\n# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID)\n# 1 to 48 octet identifier.\n# This is configured with nas_identifier (see RADIUS client section above).\n\n# Default lifetime of the PMK-RO in minutes; range 1..65535\n# (dot11FTR0KeyLifetime)\n#r0_key_lifetime=10000\n\n# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID)\n# 6-octet identifier as a hex string.\n#r1_key_holder=000102030405\n\n# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535)\n# (dot11FTReassociationDeadline)\n#reassociation_deadline=1000\n\n# List of R0KHs in the same Mobility Domain\n# format: <MAC address> <NAS Identifier> <128-bit key as hex string>\n# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC\n# address when requesting PMK-R1 key from the R0KH that the STA used during the\n# Initial Mobility Domain Association.\n#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f\n#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff\n# And so on.. One line per R0KH.\n\n# List of R1KHs in the same Mobility Domain\n# format: <MAC address> <R1KH-ID> <128-bit key as hex string>\n# This list is used to map R1KH-ID to a destination MAC address when sending\n# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD\n# that can request PMK-R1 keys.\n#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f\n#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff\n# And so on.. One line per R1KH.\n\n# Whether PMK-R1 push is enabled at R0KH\n# 0 = do not push PMK-R1 to all configured R1KHs (default)\n# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived\n#pmk_r1_push=1\n\n##### Neighbor table ##########################################################\n# Maximum number of entries kept in AP table (either for neigbor table or for\n# detecting Overlapping Legacy BSS Condition). The oldest entry will be\n# removed when adding a new entry that would make the list grow over this\n# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is\n# enabled, so this field should not be set to 0 when using IEEE 802.11g.\n# default: 255\n#ap_table_max_size=255\n\n# Number of seconds of no frames received after which entries may be deleted\n# from the AP table. Since passive scanning is not usually performed frequently\n# this should not be set to very small value. In addition, there is no\n# guarantee that every scan cycle will receive beacon frames from the\n# neighboring APs.\n# default: 60\n#ap_table_expiration_time=3600\n\n\n##### Wi-Fi Protected Setup (WPS) #############################################\n\n# WPS state\n# 0 = WPS disabled (default)\n# 1 = WPS enabled, not configured\n# 2 = WPS enabled, configured\n#wps_state=2\n\n# AP can be configured into a locked state where new WPS Registrar are not\n# accepted, but previously authorized Registrars (including the internal one)\n# can continue to add new Enrollees.\n#ap_setup_locked=1\n\n# Universally Unique IDentifier (UUID; see RFC 4122) of the device\n# This value is used as the UUID for the internal WPS Registrar. If the AP\n# is also using UPnP, this value should be set to the device's UPnP UUID.\n# If not configured, UUID will be generated based on the local MAC address.\n#uuid=12345678-9abc-def0-1234-56789abcdef0\n\n# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs\n# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the\n# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of\n# per-device PSKs is recommended as the more secure option (i.e., make sure to\n# set wpa_psk_file when using WPS with WPA-PSK).\n\n# When an Enrollee requests access to the network with PIN method, the Enrollee\n# PIN will need to be entered for the Registrar. PIN request notifications are\n# sent to hostapd ctrl_iface monitor. In addition, they can be written to a\n# text file that could be used, e.g., to populate the AP administration UI with\n# pending PIN requests. If the following variable is set, the PIN requests will\n# be written to the configured file.\n#wps_pin_requests=/var/run/hostapd_wps_pin_requests\n\n# Device Name\n# User-friendly description of device; up to 32 octets encoded in UTF-8\n#device_name=Wireless AP\n\n# Manufacturer\n# The manufacturer of the device (up to 64 ASCII characters)\n#manufacturer=Company\n\n# Model Name\n# Model of the device (up to 32 ASCII characters)\n#model_name=WAP\n\n# Model Number\n# Additional device description (up to 32 ASCII characters)\n#model_number=123\n\n# Serial Number\n# Serial number of the device (up to 32 characters)\n#serial_number=12345\n\n# Primary Device Type\n# Used format: <categ>-<OUI>-<subcateg>\n# categ = Category as an integer value\n# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for\n#       default WPS OUI\n# subcateg = OUI-specific Sub Category as an integer value\n# Examples:\n#   1-0050F204-1 (Computer / PC)\n#   1-0050F204-2 (Computer / Server)\n#   5-0050F204-1 (Storage / NAS)\n#   6-0050F204-1 (Network Infrastructure / AP)\n#device_type=6-0050F204-1\n\n# OS Version\n# 4-octet operating system version number (hex string)\n#os_version=01020300\n\n# Config Methods\n# List of the supported configuration methods\n# Available methods: usba ethernet label display ext_nfc_token int_nfc_token\n#\tnfc_interface push_button keypad virtual_display physical_display\n#\tvirtual_push_button physical_push_button\n#config_methods=label virtual_display virtual_push_button keypad\n\n# WPS capability discovery workaround for PBC with Windows 7\n# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting\n# as a Registrar and using M1 from the AP. The config methods attribute in that\n# message is supposed to indicate only the configuration method supported by\n# the AP in Enrollee role, i.e., to add an external Registrar. For that case,\n# PBC shall not be used and as such, the PushButton config method is removed\n# from M1 by default. If pbc_in_m1=1 is included in the configuration file,\n# the PushButton config method is left in M1 (if included in config_methods\n# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label\n# in the AP).\n#pbc_in_m1=1\n\n# Static access point PIN for initial configuration and adding Registrars\n# If not set, hostapd will not allow external WPS Registrars to control the\n# access point. The AP PIN can also be set at runtime with hostapd_cli\n# wps_ap_pin command. Use of temporary (enabled by user action) and random\n# AP PIN is much more secure than configuring a static AP PIN here. As such,\n# use of the ap_pin parameter is not recommended if the AP device has means for\n# displaying a random PIN.\n#ap_pin=12345670\n\n# Skip building of automatic WPS credential\n# This can be used to allow the automatically generated Credential attribute to\n# be replaced with pre-configured Credential(s).\n#skip_cred_build=1\n\n# Additional Credential attribute(s)\n# This option can be used to add pre-configured Credential attributes into M8\n# message when acting as a Registrar. If skip_cred_build=1, this data will also\n# be able to override the Credential attribute that would have otherwise been\n# automatically generated based on network configuration. This configuration\n# option points to an external file that much contain the WPS Credential\n# attribute(s) as binary data.\n#extra_cred=hostapd.cred\n\n# Credential processing\n#   0 = process received credentials internally (default)\n#   1 = do not process received credentials; just pass them over ctrl_iface to\n#\texternal program(s)\n#   2 = process received credentials internally and pass them over ctrl_iface\n#\tto external program(s)\n# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and\n# extra_cred be used to provide the Credential data for Enrollees.\n#\n# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file\n# both for Credential processing and for marking AP Setup Locked based on\n# validation failures of AP PIN. An external program is responsible on updating\n# the configuration appropriately in this case.\n#wps_cred_processing=0\n\n# AP Settings Attributes for M7\n# By default, hostapd generates the AP Settings Attributes for M7 based on the\n# current configuration. It is possible to override this by providing a file\n# with pre-configured attributes. This is similar to extra_cred file format,\n# but the AP Settings attributes are not encapsulated in a Credential\n# attribute.\n#ap_settings=hostapd.ap_settings\n\n# WPS UPnP interface\n# If set, support for external Registrars is enabled.\n#upnp_iface=br0\n\n# Friendly Name (required for UPnP)\n# Short description for end use. Should be less than 64 characters.\n#friendly_name=WPS Access Point\n\n# Manufacturer URL (optional for UPnP)\n#manufacturer_url=http://www.example.com/\n\n# Model Description (recommended for UPnP)\n# Long description for end user. Should be less than 128 characters.\n#model_description=Wireless Access Point\n\n# Model URL (optional for UPnP)\n#model_url=http://www.example.com/model/\n\n# Universal Product Code (optional for UPnP)\n# 12-digit, all-numeric code that identifies the consumer package.\n#upc=123456789012\n\n##### Wi-Fi Direct (P2P) ######################################################\n\n# Enable P2P Device management\n#manage_p2p=1\n\n# Allow cross connection\n#allow_cross_connection=1\n\n#### TDLS (IEEE 802.11z-2010) #################################################\n\n# Prohibit use of TDLS in this BSS\n#tdls_prohibit=1\n\n# Prohibit use of TDLS Channel Switching in this BSS\n#tdls_prohibit_chan_switch=1\n\n##### IEEE 802.11v-2011 #######################################################\n\n# Time advertisement\n# 0 = disabled (default)\n# 2 = UTC time at which the TSF timer is 0\n#time_advertisement=2\n\n# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:\n# stdoffset[dst[offset][,start[/time],end[/time]]]\n#time_zone=EST5\n\n##### IEEE 802.11u-2011 #######################################################\n\n# Enable Interworking service\n#interworking=1\n\n# Access Network Type\n# 0 = Private network\n# 1 = Private network with guest access\n# 2 = Chargeable public network\n# 3 = Free public network\n# 4 = Personal device network\n# 5 = Emergency services only network\n# 14 = Test or experimental\n# 15 = Wildcard\n#access_network_type=0\n\n# Whether the network provides connectivity to the Internet\n# 0 = Unspecified\n# 1 = Network provides connectivity to the Internet\n#internet=1\n\n# Additional Step Required for Access\n# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if\n# RSN is used.\n#asra=0\n\n# Emergency services reachable\n#esr=0\n\n# Unauthenticated emergency service accessible\n#uesa=0\n\n# Venue Info (optional)\n# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.\n# Example values (group,type):\n# 0,0 = Unspecified\n# 1,7 = Convention Center\n# 1,13 = Coffee Shop\n# 2,0 = Unspecified Business\n# 7,1  Private Residence\n#venue_group=7\n#venue_type=1\n\n# Homogeneous ESS identifier (optional; dot11HESSID)\n# If set, this shall be identifical to one of the BSSIDs in the homogeneous\n# ESS and this shall be set to the same value across all BSSs in homogeneous\n# ESS.\n#hessid=02:03:04:05:06:07\n\n# Roaming Consortium List\n# Arbitrary number of Roaming Consortium OIs can be configured with each line\n# adding a new OI to the list. The first three entries are available through\n# Beacon and Probe Response frames. Any additional entry will be available only\n# through ANQP queries. Each OI is between 3 and 15 octets and is configured a\n# a hexstring.\n#roaming_consortium=021122\n#roaming_consortium=2233445566\n\n##### Multiple BSSID support ##################################################\n#\n# Above configuration is using the default interface (wlan#, or multi-SSID VLAN\n# interfaces). Other BSSIDs can be added by using separator 'bss' with\n# default interface name to be allocated for the data packets of the new BSS.\n#\n# hostapd will generate BSSID mask based on the BSSIDs that are\n# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is\n# not the case, the MAC address of the radio must be changed before starting\n# hostapd (ifconfig wlan0 hw ether <MAC addr>). If a BSSID is configured for\n# every secondary BSS, this limitation is not applied at hostapd and other\n# masks may be used if the driver supports them (e.g., swap the locally\n# administered bit)\n#\n# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is\n# specified using the 'bssid' parameter.\n# If an explicit BSSID is specified, it must be chosen such that it:\n# - results in a valid MASK that covers it and the dev_addr\n# - is not the same as the MAC address of the radio\n# - is not the same as any other explicitly specified BSSID\n#\n# Please note that hostapd uses some of the values configured for the first BSS\n# as the defaults for the following BSSes. However, it is recommended that all\n# BSSes include explicit configuration of all relevant configuration items.\n#\n#bss=wlan0_0\n#ssid=test2\n# most of the above items can be used here (apart from radio interface specific\n# items, like channel)\n\n#bss=wlan0_1\n#bssid=00:13:10:95:fe:0b\n# ...\n"
  },
  {
    "path": "hostapd_wrapper/hostapd2/hostapd_linux_ac.conf",
    "content": "ip_daemon_ac=127.0.0.1\nsock_path_ac=/tmp/ac_ipc_hostapd\nport_daemon_ac=5543\n"
  },
  {
    "path": "hostapd_wrapper/hostapd2/linux-ac.sh",
    "content": "#/bin/sh\ncp -f hostapd_linux.conf /etc/hostapd.conf\ncp -f hostapd_linux_ac.conf /etc/hostapd_ac.conf\napt-get -y purge libnl1 libnl2 hostapd\napt-get -y autoremove\nrm -rf /tmp/hostapd-linux/\nmkdir -p /tmp/hostapd-linux\ncp -f *.tar.* *.patch /tmp/hostapd-linux\ncd /tmp/hostapd-linux\ntar zxvf nl-tiny.tar.gz\nmv src nl-tiny\ncd nl-tiny/\nrm -rf *.o\nmake\ncp libnl-tiny.so /usr/lib\ncp -rf include/* /usr/include/\nldconfig -v | grep tiny\ncd ..\nrm -rf nl-tiny\ntar jxvf hostapd-20130302.tar.bz2\ncd hostapd-20130302\npatch -p1 < ../hostapd-20130302-linux.patch\ncd hostapd\nCFLAGS=\"-DCONFIG_LIBNL20 -D_GNU_SOURCE -DCONFIG_MSG_MIN_PRIORITY=3 -Os -pipe -fno-caller-saves -ffunction-sections -fdata-sections -DNETUDP\" make CONFIG_DRIVER_NL80211=y CONFIG_DRIVER_MADWIFI= CONFIG_DRIVER_HOSTAP= CONFIG_IEEE80211N=y CONFIG_IEEE80211W=y CONFIG_DRIVER_WEXT=  LIBS=\"-lm -lnl-tiny\" BCHECK=  hostapd hostapd_cli\ncp -f hostapd /usr/sbin/hostapd\napt-get -y install iw\ncd ~\nrm -rf /tmp/hostapd-linux\n"
  },
  {
    "path": "hostapd_wrapper/hostapd_ac.conf",
    "content": "ip_daemon_ac=127.0.0.1\nsock_path_ac=/tmp/ac_ipc_hostapd\nport_daemon_ac=5543\n"
  },
  {
    "path": "hostapd_wrapper/hostapd_wtp.conf",
    "content": "ip_daemon_wtp=127.0.0.1\nport_daemon_wtp=6333\nsock_pach_wtp=/tmp/wtp_ipc_hostapd\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/capwap_mgmt_frame_ac.c",
    "content": "#include \"utils/includes.h\"\n\n#include \"utils/common.h\"\n#include \"radius/radius.h\"\n#include \"drivers/driver.h\"\n#include \"common/ieee802_11_defs.h\"\n#include \"common/ieee802_11_common.h\"\n#include \"common/wpa_ctrl.h\"\n#include \"crypto/random.h\"\n\n\n#define MAC_LENGTH 6\n#define HLEN_80211 24\n#define HLEN_LLC 8\n\nint same_mac( unsigned char *mac1, unsigned char *mac2){// return 0\n\tint i;\n\tfor(i=0;i<MAC_LENGTH;i++)if(mac1[i]!=mac2[i])return -1;\n\treturn 0;\n}\n\nint GetEapol_Frame( unsigned char *sa,  unsigned char *buf, int len){\n\tstruct ieee80211_hdr *hdr;\n\thdr = (struct ieee80211_hdr *) buf;\n\tos_memcpy(sa, hdr->addr2, MAC_LENGTH);\n\treturn HLEN_80211 + HLEN_LLC;\n}\n\nint isEAPOL_Frame( unsigned char *buf, int len){\n\tunsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n\tint i;\n\n\tfor(i=0; i<6; i++)if(rfc1042_header[i]!=buf[i + HLEN_80211])return 0;\n\treturn 1;\n}\n\nvoid stampa_mac(char *s,  unsigned char *mac){\n\tint i;\n\twpa_printf(MSG_DEBUG,\"%s\",s);\n\tfor(i=0; i<6; i++)wpa_printf(MSG_DEBUG,\"%02X \",mac[i]);\n\twpa_printf(MSG_DEBUG,\"\\n\");\n}\n\nvoid stamp_all_max( unsigned char *buf,  unsigned char *own_mac){\n\tstruct ieee80211_hdr *hdr;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\n\tstampa_mac(\"addr1 \",hdr->addr1);\n\tstampa_mac(\"addr2 \",hdr->addr2);\n\tstampa_mac(\"addr3 \",hdr->addr3);\n\tstampa_mac(\"own_mac \", own_mac);\n}\n\nint isCallBackFrame( unsigned char *buf, int len,  unsigned char *own_mac){\n\t// return 1 if is it CALL Back Frame\n\t// return 0 if is NOT CALL Back Frame\n\tstruct ieee80211_hdr *hdr;\n/*\n\tu16 fc;\n*/\n\n\thdr = (struct ieee80211_hdr *) buf;\n/* capwap FIXME: needed?\n\tfc = le_to_host16(hdr->frame_control);\n*/\n\n\tif( same_mac(hdr->addr2,own_mac)==0 && same_mac(hdr->addr3,own_mac)==0 )return 1;\n\treturn 0;\n}\n\nint AC_get_SubType( unsigned char *buf, int len){\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\treturn WLAN_FC_GET_STYPE(fc);\n}\n\nint AC_get_Type( unsigned char *buf, int len){\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\treturn WLAN_FC_GET_TYPE(fc);\n}\n\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/capwap_mgmt_frame_ac.h",
    "content": "#ifndef __CAPWAP_MGMT_FRAME_AC_H\n#define __CAPWAP_MGMT_FRAME_AC_H\n\n#include \"drivers/driver.h\"\n\nint GetEapol_Frame( unsigned char *sa,  unsigned char *buf, int len);\n\nint isEAPOL_Frame( unsigned char *buf, int len);\n\nint isCallBackFrame( unsigned char *buf, int len,  unsigned char *own_mac);\n\nint AC_get_SubType( unsigned char *buf, int len);\n\nint AC_get_Type( unsigned char *buf, int len);\n\n#endif\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/capwap_mgmt_frame_wtp.c",
    "content": "#include \"utils/includes.h\"\n\n#include \"utils/common.h\"\n#include \"radius/radius.h\"\n#include \"drivers/driver.h\"\n#include \"common/ieee802_11_defs.h\"\n#include \"common/ieee802_11_common.h\"\n#include \"common/wpa_ctrl.h\"\n#include \"crypto/random.h\"\n#include \"p2p/p2p.h\"\n#include \"wps/wps.h\"\n#include \"ap/hostapd.h\"\n#include \"ap/ieee802_11.h\"\n#include \"ap/sta_info.h\"\n#include \"ap/accounting.h\"\n#include \"ap/tkip_countermeasures.h\"\n#include \"ap/iapp.h\"\n#include \"ap/ieee802_1x.h\"\n#include \"ap/wpa_auth.h\"\n#include \"ap/wmm.h\"\n#include \"ap/wps_hostapd.h\"\n#include \"ap/ap_drv_ops.h\"\n#include \"ap/ap_config.h\"\n\n#define HAPD_BROADCAST ((struct hostapd_data *) -1)\n#define HLEN_80211\t24\n\nvoid WTP_handle_assoc_cb(struct hostapd_data *hapd,const struct ieee80211_mgmt *mgmt,size_t len, int reassoc, int ok){\n\twpa_printf(MSG_DEBUG,\"WTP: WTP_handle_assoc_cb\\n\");\n\tu16 status;\n\tstruct sta_info *sta;\n\tint new_assoc = 1;\n\n\tif (!ok) {\n\t\thostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,\n\t\t\t       HOSTAPD_LEVEL_DEBUG,\n\t\t\t       \"did not acknowledge association response\");\n\t\treturn;\n\t}\n\n\tif (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :\n\t\t\t\t      sizeof(mgmt->u.assoc_resp))) {\n\t\tprintf(\"handle_assoc_cb(reassoc=%d) - too short payload \"\n\t\t       \"(len=%lu)\\n\", reassoc, (unsigned long) len);\n\t\treturn;\n\t}\n\n\tif (reassoc)\n\t\tstatus = le_to_host16(mgmt->u.reassoc_resp.status_code);\n\telse\n\t\tstatus = le_to_host16(mgmt->u.assoc_resp.status_code);\n\n\tap_sta_add(hapd, mgmt->da);\n\tsta = ap_get_sta(hapd, mgmt->da);\n\n\tstatic  unsigned char sup[4]={ 0x82 ,0x84 ,0x8B ,0x96 };\n\n\thostapd_sta_add(hapd, sta->addr, ( unsigned short)1, ( unsigned short)33,  sup, 4,\n\t\t\t    (u16)1,\n\t\t\t    NULL,\n\t\t\t    (u32)32931);\n\treturn ;\n\n}\n\nstruct hostapd_data * WTP_get_hapd_bssid(struct hostapd_iface *iface,const  unsigned char *bssid){\n\tsize_t i;\n\tif (bssid == NULL)\n\t\treturn NULL;\n\tif (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&\n\t    bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)\n\t\treturn HAPD_BROADCAST;\n\n\tfor (i = 0; i < iface->num_bss; i++) {\n\t\tif (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)\n\t\t\treturn iface->bss[i];\n\t}\n\treturn NULL;\n}\n\nvoid WTP_handle_tx_callback_ASS_RES(void *ctx,  unsigned char *buf, size_t len, int ok){\n\treturn;\n\tstruct ieee80211_hdr *hdr;\n\tconst struct ieee80211_mgmt *mgmt;\n\n\tu16 fc;\n\tunion wpa_event_data event;\n    struct hostapd_data *hapd=ctx;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tmgmt = (const struct ieee80211_mgmt *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\tos_memset(&event, 0, sizeof(event));\n\tevent.tx_status.type = WLAN_FC_GET_TYPE(fc);\n\tevent.tx_status.stype = WLAN_FC_GET_STYPE(fc);\n\tevent.tx_status.dst = hdr->addr1;\n\tevent.tx_status.data = buf;\n\tevent.tx_status.data_len = len;\n\tevent.tx_status.ack = ok;\n\n\t//hapd = WTP_get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));\n\t//if (hapd == NULL || hapd == HAPD_BROADCAST)\n\t//\treturn;\n\n\tif(event.tx_status.stype==WLAN_FC_STYPE_ASSOC_RESP)\n\t\tWTP_handle_assoc_cb(hapd, mgmt, len, 0, ok);\n\telse\n\t\tWTP_handle_assoc_cb(hapd, mgmt, len, 1, ok);\n\n}\n\nint isEAPOL_Frame( unsigned char *buf, int len){\n\tunsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n\tint i;\n\n\tfor(i=0; i<6; i++)if(rfc1042_header[i]!=buf[i + HLEN_80211])return 0;\n\treturn 1;\n}\n\nint WTP_get_SubType( unsigned char *buf,int len){\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\treturn WLAN_FC_GET_STYPE(fc);\n}\n\nint WTP_get_Type( unsigned char*buf,int len){\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\treturn WLAN_FC_GET_TYPE(fc);\n}\n\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/capwap_mgmt_frame_wtp.h",
    "content": "#ifndef __CAPWAP_MGMT_FRAME_WTP_H\n#define __CAPWAP_MGMT_FRAME_WTP_H\n\n#include \"drivers/driver.h\"\n#include \"ap/hostapd.h\"\n\nvoid WTP_handle_assoc_cb(struct hostapd_data *hapd,const struct ieee80211_mgmt *mgmt,size_t len, int reassoc, int ok);\n\nvoid WTP_ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,u16 stype, int ok);\n\nstruct hostapd_data * WTP_get_hapd_bssid(struct hostapd_iface *iface,const u8 *bssid);\n\nvoid WTP_hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,size_t len, u16 stype, int ok);\n\nvoid WTP_wpa_supplicant_event(void *ctx, enum wpa_event_type event,union wpa_event_data *data);\n\n\nint WTP_get_SubType(u8 *buf,int len);\n\nint WTP_get_Type(u8 *buf,int len);\n\nint isEAPOL_Frame( unsigned char *buf, int len);\n\n#endif\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/file_conf_ac.h",
    "content": "#define CONFIGFILE \"hostapd_ac.conf\"\n#define VARLENGTH 1024\n\nstruct config_ac {\n\tint ac_port;\n\tchar ip_ac[50];\n\tchar path_unix_socket[50];\n}config_ac;\n\nint max_(int integer1,int integer2){\n\tif(integer1>integer2)return integer1;\n\treturn integer2;\n}\n\nint countString(char string[]){\n\tint cnt=0;\n\tfor(cnt=0;string[cnt]!=0;cnt++);\n\treturn cnt;\n}\n\nint isEqualString(char String1[],char String2[]){\n\tint len1=countString(String1);\n\tint len2=countString(String2);\n\tint i;\n\tfor( i=0;i<max_(len1,len2);++i ){\n\t\tif ( String1[i]==0 && String2[i]==0 )return 1;\n\t\tif ( String1[i]==0 || String2[i]==0 )return 0;\n\t\tif ( String1[i]!=String2[i] )return 0;\n\t}\n\treturn 1;\n}\n\nint StartWith(char String1[],char String2[]){\n\tint len2=countString(String2);\n\tint i;\n\n\tfor( i=0; i<len2;i++ ){\n\n\t\tif ( String1[i]!=String2[i] )return 0;\n\t}\n\n\treturn 1;\n}\n\nvoid ReplaceString(char *String1,char *rep,char *String2){\n\tif(isEqualString(String1,rep)){\n\t\tString1[0]=0;\n\t\treturn;\n\t}\n\tif(String1[0]==0 || rep[0]==0)return;\n\tint i,j,k,b,l,m;\n\tchar tmp[strlen(String1)+strlen(String2)+1];\n\tfor(i=0;i<=strlen(String1)+strlen(String2)-1;i++)tmp[i]=88;\n\ttmp[i]=0;\n\tfor(i=0;i<=strlen(String1)-1;i++){\n\t\tif(strlen(rep)>=1)b=1;\n\t\tfor(j=0;j<=strlen(rep)-1;j++){\n\t\t\tif(String1[i+j]!=rep[j]){\n\t\t\t\tb=0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif(b){\n\t\t\tfor(k=0;k<i;k++)tmp[k]=String1[k];\n\t\t\tif(strlen(String2)>0){\n\t\t\t\tfor(m=0;m<=strlen(String2)-1;++m,k++)tmp[k]=String2[m];\n\t\t\t}\n\t\t\tfor(l=i+j;l<=strlen(String1)-1;l++,k++)tmp[k]=String1[l];\n\t\t\ttmp[k]=0;\n\n\t\t\tfor(k=0;k<strlen(tmp);k++)String1[k]=tmp[k];\n\t\t\tif (String1[k-1]==10)String1[k-1]=0;\n\t\t\telse \tString1[k]=0;\n\t\t}\n\t}\n}\n\nvoid ReadConfiguration(struct config_ac *con_ac){\n\tFILE *file;\n\n    file=fopen(CONFIGFILE,\"r\");\n\n\tchar ss[VARLENGTH];\n\n\tmemset(con_ac, 0, sizeof(struct config_ac));\n\n\twhile(1){\n\t\tif (fgets(ss,VARLENGTH,file)==NULL)break;\n\t\tif(ss[0]=='\\r' || ss[0]=='\\n' || ss[0]=='#')continue;\n\n\t\tif(StartWith(ss,\"ip_daemon_ac\")){\n\t\t\tReplaceString(ss, \"ip_daemon_ac\", \"\");\n\t\t\tReplaceString(ss, \"=\", \"\");\n\t\t\tReplaceString(ss, \"\\n\", \"\");\n\t\t\tReplaceString(ss, \" \", \"\");\n\t\t\tsprintf(con_ac->ip_ac, \"%s\", ss);\n\n\t\t}else if(StartWith(ss,\"sock_path_ac\")){\n\t\t\tReplaceString(ss, \"sock_path_ac\", \"\");\n\t\t\tReplaceString(ss, \"=\", \"\");\n\t\t\tReplaceString(ss, \"\\n\", \"\");\n\t\t\tReplaceString(ss, \" \", \"\");\n\t\t\tsprintf(con_ac->path_unix_socket, \"%s\", ss);\n\n\t\t}else if(StartWith(ss,\"port_daemon_ac\")){\n\t\t\tReplaceString(ss, \"port_daemon_ac\",\"\");\n\t\t\tReplaceString(ss, \"\\n\", \"\");\n\t\t\tReplaceString(ss, \" \", \"\");\n\t\t\tReplaceString(ss, \"=\", \"\");\n\t\t\tcon_ac->ac_port = atoi(ss);\n\t\t}\n\n\t}\n\tfclose(file);\n\treturn;\n}\n\n\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/file_conf_wtp.h",
    "content": "#define CONFIGFILE \"hostapd_wtp.conf\"\n#define VARLENGTH 1024\n\nstruct config_wtp {\n\tint wtp_port;\n\tchar ip_wtp[50];\n\tchar path_unix_socket[50];\n}config_wtp;\n\nint max_(int integer1,int integer2){\n\tif(integer1>integer2)return integer1;\n\treturn integer2;\n}\n\nint countString(char string[]){\n\tint cnt=0;\n\tfor(cnt=0;string[cnt]!=0;cnt++);\n\treturn cnt;\n}\n\nint isEqualString(char String1[],char String2[]){\n\tint len1=countString(String1);\n\tint len2=countString(String2);\n\tint i;\n\tfor( i=0;i<max_(len1,len2);++i ){\n\t\tif ( String1[i]==0 && String2[i]==0 )return 1;\n\t\tif ( String1[i]==0 || String2[i]==0 )return 0;\n\t\tif ( String1[i]!=String2[i] )return 0;\n\t}\n\treturn 1;\n}\n\nint StartWith(char String1[],char String2[]){\n\tint len2=countString(String2);\n\tint i;\n\n\tfor( i=0; i<len2;i++ ){\n\n\t\tif ( String1[i]!=String2[i] )return 0;\n\t}\n\n\treturn 1;\n}\n\nvoid ReplaceString(char *String1,char *rep,char *String2){\n\tif(isEqualString(String1,rep)){\n\t\tString1[0]=0;\n\t\treturn;\n\t}\n\tif(String1[0]==0 || rep[0]==0)return;\n\tint i,j,k,b,l,m;\n\tchar tmp[strlen(String1)+strlen(String2)+1];\n\tfor(i=0;i<=strlen(String1)+strlen(String2)-1;i++)tmp[i]=88;\n\ttmp[i]=0;\n\tfor(i=0;i<=strlen(String1)-1;i++){\n\t\tif(strlen(rep)>=1)b=1;\n\t\tfor(j=0;j<=strlen(rep)-1;j++){\n\t\t\tif(String1[i+j]!=rep[j]){\n\t\t\t\tb=0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif(b){\n\t\t\tfor(k=0;k<i;k++)tmp[k]=String1[k];\n\t\t\tif(strlen(String2)>0){\n\t\t\t\tfor(m=0;m<=strlen(String2)-1;++m,k++)tmp[k]=String2[m];\n\t\t\t}\n\t\t\tfor(l=i+j;l<=strlen(String1)-1;l++,k++)tmp[k]=String1[l];\n\t\t\ttmp[k]=0;\n\n\t\t\tfor(k=0;k<strlen(tmp);k++)String1[k]=tmp[k];\n\t\t\tif (String1[k-1]==10)String1[k-1]=0;\n\t\t\telse \tString1[k]=0;\n\t\t}\n\t}\n}\n\nvoid ReadConfiguration(struct config_wtp *con_wtp){\n\tFILE *file;\n\n    file=fopen(CONFIGFILE,\"r\");\n\n\tchar ss[VARLENGTH];\n\n\tmemset(con_wtp, 0, sizeof(struct config_wtp));\n\n\twhile(1){\n\t\tif (fgets(ss,VARLENGTH,file)==NULL)break;\n\t\tif(ss[0]=='\\r' || ss[0]=='\\n' || ss[0]=='#')continue;\n\n\t\tif(StartWith(ss,\"ip_daemon_wtp\")){\n\t\t\tReplaceString(ss, \"ip_daemon_wtp\", \"\");\n\t\t\tReplaceString(ss, \"=\", \"\");\n\t\t\tReplaceString(ss, \"\\n\", \"\");\n\t\t\tReplaceString(ss, \" \", \"\");\n\t\t\tsprintf(con_wtp->ip_wtp, \"%s\", ss);\n\n\t\t}else if(StartWith(ss,\"sock_pach_wtp\")){\n\t\t\tReplaceString(ss, \"sock_pach_wtp\", \"\");\n\t\t\tReplaceString(ss, \"=\", \"\");\n\t\t\tReplaceString(ss, \"\\n\", \"\");\n\t\t\tReplaceString(ss, \" \", \"\");\n\t\t\tsprintf(con_wtp->path_unix_socket, \"%s\", ss);\n\n\t\t}else if(StartWith(ss,\"port_daemon_wtp\")){\n\t\t\tReplaceString(ss, \"port_daemon_wtp\",\"\");\n\t\t\tReplaceString(ss, \"\\n\", \"\");\n\t\t\tReplaceString(ss, \" \", \"\");\n\t\t\tReplaceString(ss, \"=\", \"\");\n\t\t\tcon_wtp->wtp_port = atoi(ss);\n\t\t}\n\n\t}\n\tfclose(file);\n\treturn;\n}\n\n\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/ipc_capwap_ac.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <sys/un.h>\n#include \"eloop.h\"\n#include \"utils/includes.h\"\n\n\n#include \"utils/common.h\"\n#include \"common/ieee802_11_defs.h\"\n#include \"common/ieee802_11_common.h\"\n#include \"drivers/driver.h\"\n#include \"ap/hostapd.h\"\n#include \"ap/ap_config.h\"\n#include \"ap/ap_drv_ops.h\"\n\n#include \"ipc_capwap_ac.h\"\n#include \"file_conf_ac.h\"\n#include \"smac_code.h\"\n\n\n#define MAX_BUF 3000\n\n//#define LOCALUDP\n//#define NETUDP\n//#define USEIPV6\n\nstruct config_ac con_ac;\nunsigned char wlan0_capa[21];\n\nint fd_con;\nint tot_len;\nchar wlanbuf[MAX_BUF];\n\n#if defined(LOCALUDP)\n\tstruct sockaddr_un addr;\n\tstruct sockaddr_un local;\n\tint rn;\n\n#else\n\t#if defined(USEIPV6)\n\t\tstruct sockaddr_in6 client;\n\t\tstruct sockaddr_in6 addr;\n\t#else\n\t\tstruct sockaddr_in client;\n\t\tstruct sockaddr_in addr;\n\t#endif\n#endif\n\n#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))\n#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))\n#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))\n\nsocklen_t address_size;\n\nint capability_is_A(){\n\tif( CHECKBIT(wlan0_capa[8],1))return 1;\n\telse return 0;\n}\nint capability_is_B(){\n\tif( CHECKBIT(wlan0_capa[8],0))return 1;\n\telse return 0;\n}\nint capability_is_G(){\n\tif( CHECKBIT(wlan0_capa[8],2))return 1;\n\telse return 0;\n}\nint capability_is_N(){\n\tif( CHECKBIT(wlan0_capa[8],3))return 1;\n\telse return 0;\n}\n\nint capability_get_num_modes(){\n\tint num_modes = 0;\n\n\tif( CHECKBIT(wlan0_capa[8],0)) num_modes++;\n\tif( CHECKBIT(wlan0_capa[8],1)) num_modes++;\n\tif( CHECKBIT(wlan0_capa[8],2)) num_modes++;\n\tif( CHECKBIT(wlan0_capa[8],3)) num_modes++;\n\n\treturn num_modes;\n}\n\nint capability_get_first_channel(){\n\treturn (int)wlan0_capa[10];\n}\n\nint capability_get_num_channels(){\n\treturn (int)wlan0_capa[12];\n}\n\nint capability_get_max_dBm(){\n\treturn (int)wlan0_capa[14];\n}\n\nint capability_get_rates(int *rate_arr){\n\tint num_rates = 0;\n\tint i;\n\tfor(i=0; i<8; i++){\n\t\tif( wlan0_capa[i]==0 ) continue;\n\n\t\tif( CHECKBIT(wlan0_capa[i],7) ){\n\t\t\tCLEARBIT(wlan0_capa[i],7);\n\t\t\trate_arr[num_rates] = (int)(wlan0_capa[i] * -5);\n\t\t}else{\n\t\t\trate_arr[num_rates] = (int)(wlan0_capa[i] * 5);\n\t\t}\n\t\tnum_rates++;\n\t}\n\treturn num_rates;\n}\n\nvoid capability_get_mac(unsigned char *buf) {\n\tmemcpy(buf, wlan0_capa + 15, 6);\n}\n\nvoid prep_beacon(int fd,struct hostapd_data *hapd,struct wpa_driver_ap_params *params){\n\tstruct hostapd_data *h = hapd;\n\tshort ssid_len = (short)h->conf->ssid.ssid_len;\n\tshort key_len = (short) h->conf->ssid.wep.len[h->conf->ssid.wep.idx];\n\n\n\twpa_printf(MSG_DEBUG,\"SSID: %s ssid_len:%d\\n\",h->conf->ssid.ssid,ssid_len);\n\twpa_printf(MSG_DEBUG,\"IDX:%d   key_len:%d    key:%s  \\n\",h->conf->ssid.wep.idx,key_len,h->conf->ssid.wep.key[h->conf->ssid.wep.idx]);\n\n\tunsigned char A1 = 0;\n\tunsigned char A2 = 0;\n\n\tSETBIT(A1,7); \t//E (ESS)\n\tCLEARBIT(A1,6); //I (IBSS)\n\tCLEARBIT(A1,5); //C (CF Pollable)\n\tCLEARBIT(A1,4); //F (CF Pollable Request)\n\tif(params->privacy)\t\tSETBIT(A1,3); //P (Privacy)\n\telse\t\t\t\t\tCLEARBIT(A1,3); //P (Privacy)\n\tif(params->preamble)\tSETBIT(A1,2); //S (Sort Preamble)\n\telse    \t\t\t\tCLEARBIT(A1,2); //S (Sort Preamble)\n\tCLEARBIT(A1,1); //B (PBCC)\n\tCLEARBIT(A1,0); //A (Channel Agility)\n\n\tCLEARBIT(A2,7); //I (IBSS)\n\tCLEARBIT(A2,6); //I (IBSS)\n\tif(params->short_slot_time)\t\tSETBIT(A2,5); //I (IBSS)\n\telse  \t\t\t\t\t\t\tCLEARBIT(A2,5); //I (IBSS)\n\tCLEARBIT(A2,4); //I (IBSS)\n\tCLEARBIT(A2,3); //I (IBSS)\n\tCLEARBIT(A2,2); //I (IBSS)\n\tCLEARBIT(A2,1); //I (IBSS)\n\tCLEARBIT(A2,0); //I (IBSS)\n\n\n\n\ttot_len = 19 + ssid_len + key_len;\n\n\n\tunsigned char buf[tot_len];\n\n\twpa_printf(MSG_DEBUG,\"Tot Len:%d \\n\",tot_len);\n\n\tbuf[0] = 0; // Radio ID\n\tbuf[1] = 0; // WLAN ID\n\tbuf[2] = A1; // Flags Part1\n\tbuf[3] = A2;  // Flags Part2\n\n\tbuf[4] = h->conf->ssid.wep.idx;  // Key Index\n\n\tif(params->privacy)\tbuf[5] = 1;  // Key Status\n\telse \t\t\t\tbuf[5] = 0;  // Key Status\n\n\twpa_printf(MSG_DEBUG,\"keylen: %d \\n\",key_len);\n\n\n\t//memcpy(buf+6, &key_len, 1);\n\t//memcpy(buf+7, &key_len, 1);\n\tbuf[6] = *(&key_len + 1);  // Key Length Part1\n\tbuf[7] = *(&key_len + 0);  // Key Length Part2\n\n\twpa_printf(MSG_DEBUG,\"keylen: %d %02X %02X \\n\",key_len,buf[6],buf[7]);\n\n\tif( key_len ) memcpy( buf + 8, h->conf->ssid.wep.key[h->conf->ssid.wep.idx], key_len);\n\n\tbuf[8+key_len] = 0;   // Group TSC Part1\n\tbuf[9+key_len] = 0;   // Group TSC Part2\n\tbuf[10+key_len] = 0;  // Group TSC Part3\n\tbuf[11+key_len] = 0;  // Group TSC Part4\n\n\tbuf[12+key_len] = 0;  // Group TSC Part5\n\tbuf[13+key_len] = 0;  // Group TSC Part6\n\tbuf[14+key_len] = 0;  // QoS\n\n\tif(params->privacy)\tbuf[15+key_len] = 1;  // Auth Type\n\telse \t\t\t\tbuf[15+key_len] = 0;  // Auth Type\n\n\tbuf[16+key_len] = 1;  // Mac Mode\n\tbuf[17+key_len] = 2;  // Tunnel Mode\n\tbuf[18+key_len] = 1;  // Suppress SSID\n\n\tmemcpy(buf + key_len + 19, h->conf->ssid.ssid, ssid_len);\n\n\tint i;\n\tfor(i=0; i<tot_len; i++){\n\t\tif((i%4)==0)printf(\"\\n\");\n\t\twpa_printf(MSG_DEBUG,\"%02X \",buf[i]);\n\t}\n\twpa_printf(MSG_DEBUG,\"\\n\");\n\tif (tot_len < MAX_BUF){ strncpy(wlanbuf, buf, tot_len); }\n\tsend_response(fd, ADD_WLAN, buf, tot_len);\n}\n\nvoid ipc_send_ADD_WLAN(int fd,char *ssid, int len){\n\n\tint new_len = 19 + len;\n\tunsigned char cmd[new_len];\n\n\n\tint i;\n\tfor(i=0; i<new_len; i++)cmd[i]=0;\n\n\tcmd[0] = 0; // Radio ID\n\tcmd[1] = 0; // WLAN ID\n\tcmd[2] = 128; // Flags Part1\n\tcmd[3] = 0;  // Flags Part2\n\n\tcmd[4] = 0;  // Key Index\n\tcmd[5] = 0;  // Key Status\n\tcmd[6] = 0;  // Key Length Part1\n\tcmd[7] = 0;  // Key Length Part2\n\n\tcmd[8] = 0;   // Group TSC Part1\n\tcmd[9] = 0;   // Group TSC Part2\n\tcmd[10] = 0;  // Group TSC Part3\n\tcmd[11] = 0;  // Group TSC Part4\n\n\tcmd[12] = 0;  // Group TSC Part5\n\tcmd[13] = 0;  // Group TSC Part6\n\tcmd[14] = 0;  // QoS\n\tcmd[15] = 0;  // Auth Type\n\n\tcmd[16] = 1;  // Mac Mode\n\tcmd[17] = 2;  // Tunnel Mode\n\tcmd[18] = 1;  // Suppress SSID\n\n\n\tmemcpy(cmd+19, ssid, len);\n\n\tsend_response(fd, ADD_WLAN, cmd, new_len);\n}\n\n\nvoid ipc_send_DEL_WLAN(int fd){\n\tunsigned char cmd[2];\n\n\tcmd[0] = 0; // Radio ID\n\tcmd[1] = 0; // WLAN ID\n\twpa_printf(MSG_DEBUG,\"DEL 1\\n\");\n\tsend_response(fd, DEL_WLAN, cmd, 2);\n}\n\nvoid ipc_send_CLOSE_to_AC(int fd){\n\tunsigned char cmd[10];\n\tsend_response(fd, CLOSE, cmd, 10);\n}\n\nvoid ipc_send_add_station(int fd, u8 *buf, int len){\n\tu16 fc;\n\tint status = -1;\n\tunsigned char cmd[6];\n\tstruct ieee80211_mgmt *mgmt;\n\tstruct ieee80211_hdr *hdr;\n\tmgmt = (struct ieee80211_mgmt *) buf;\n\thdr = (struct ieee80211_hdr *) buf;\n\n\tfc = le_to_host16(hdr->frame_control);\n\n\tif( WLAN_FC_GET_STYPE(fc)==WLAN_FC_STYPE_ASSOC_RESP ){\n\t\tstatus = le_to_host16(mgmt->u.assoc_resp.status_code);\n\n\t}else if( WLAN_FC_GET_STYPE(fc)==WLAN_FC_STYPE_REASSOC_RESP){\n\t\tstatus = le_to_host16(mgmt->u.reassoc_resp.status_code);\n\n\t}else{\n\t\twpa_printf(MSG_ERROR, \"Error: ipc_send_add_station\\n\");\n\t\treturn;\n\t}\n\n\tif(status == 0){\n\t\tmemcpy(cmd,mgmt->da,6);\n\t\tsend_response(fd, SET_ADDR, cmd, 6);\n\t}\n\n\n}\n\nvoid ipc_send_del_station(int fd, u8 *buf, int len){\n\tu16 fc;\n\tunsigned char cmd[6];\n\tstruct ieee80211_hdr *hdr;\n\thdr = (struct ieee80211_hdr *) buf;\n\n\tfc = le_to_host16(hdr->frame_control);\n\n\tif( WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_DISASSOC ){\n\t\twpa_printf(MSG_DEBUG,\"Il pacchetto non e' di tipo DISASSOC\\n\");\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG,\"DEL ADDR: %02X %02X %02X %02X %02X %02X \\n\",hdr->addr2[0],hdr->addr2[1],hdr->addr2[2],hdr->addr2[3],hdr->addr2[4],hdr->addr2[5]);\n\n\tmemcpy(cmd,hdr->addr2,6);\n\tsend_response(fd, DEL_ADDR, cmd, 6);\n\n}\n\nvoid ipc_send_80211_to_wtp(int fd, u8 *buf, int len){\n\n\tsend_response(fd, DATE_TO_WTP, buf, len);\n}\n\nvoid send_response(int fd, u8 code, u8 *buf, int len){\n\tu8 tmp_buf[MAX_BUF];\n\ttmp_buf[0] = code;\n\n\tint n;\n\n\t#if defined(LOCALUDP)\n\t\tsprintf(tmp_buf + 1, \"%05d\", rn);\n\t\tmemcpy(tmp_buf + 6, buf, len);\n\t\tn = sendto(fd, tmp_buf, len + 6, 0, (struct sockaddr *)&addr, address_size);\n\t#else\n\t\tmemcpy(tmp_buf + 1, buf, len);\n\t\tn = sendto(fd, tmp_buf, len + 1, 0, (struct sockaddr *)&addr, address_size);\n\t#endif\n\n\n\tif ( n < 0 ) {\n\t\tperror(\"send\");\n\t\treturn;\n\t}\n\n}\n\n\nvoid management_recv(int fd, u8 code, u8 *buf, int len, void *hapd, void *inject_func){\n\n\ttruct hostapd_data *h = hapd;\n\tif(code == PING){\n\t\tsend_response(fd, PONG, buf, len);\n\t}else if (code == SEND_WLAN) {\n\t\tsend_response(fd, ADD_WLAN, wlanbuf, tot_len);\n\t}else if( code==DATE_TO_AC ){\n\t\tstruct hostapd_data *h = hapd;\n\t\tvoid (*pointer_inject_frame_in_hostapd) (void*,unsigned char*,int);\n\t\tpointer_inject_frame_in_hostapd = inject_func;\n\t\tpointer_inject_frame_in_hostapd(h->drv_priv, buf, len);\n\t\t//hostapd_inject_frame_in_hostapd(h, buf, len);\n\n\t}else{\n\t\twpa_printf(MSG_DEBUG,\"ERROR IPC: received unrecognizedcode: %d\\n\",code);\n\t}\n\n}\n\nvoid recv_request(int fd,void *hapd, void *inject_func)\n{\n\tunsigned char str[MAX_BUF];\n\tint n;\n\n#if defined(LOCALUDP)\n\tn = recvfrom(fd, str, MAX_BUF, 0, (struct sockaddr *)&local, &address_size);\n#else\n\tn = recvfrom(fd, str, MAX_BUF, 0, (struct sockaddr *)&addr, &address_size);\n#endif\n\n\tif(n<=0){\n\t\tend_ipc(fd);\n\t\treturn;\n\t}\n\n\tmanagement_recv(fd, str[0], str + 1, n -1, hapd, inject_func);\n}\n\n\n\nint open_socket()\n{\n\tint fd_ac;\n\n\tchar buffer[100];\n\n#if defined(LOCALUDP)\n\tsrand((unsigned)time(0));\n\tfd_ac = socket(AF_UNIX, SOCK_DGRAM, 0);\n\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tfd_ac = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);\n#else\n\tfd_ac = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n#endif\n\n#else\n#if defined(USEIPV6)\n\tfd_ac = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);\n#else\n\tfd_ac = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);\n#endif\n\n#endif\n\n#if defined(LOCALUDP)\n\taddr.sun_family = AF_UNIX;\n\tstrcpy(addr.sun_path, con_ac.path_unix_socket);\n\tlocal.sun_family = AF_UNIX;\n\n\twhile(1){\n\t\trn = rand()%100000;\n\t\tsprintf(local.sun_path, \"%s%05d\", con_ac.path_unix_socket, rn);\n\t\tif( bind(fd_ac, (struct sockaddr *)&local, strlen(local.sun_path) + sizeof(local.sun_family))==-1){\n\t\t\tsleep(1);\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\twpa_printf(MSG_DEBUG,\"Connect to %s from %s\\n\",addr.sun_path, local.sun_path);\n#else\n\n#if defined(USEIPV6)\n\taddr.sin6_family = AF_INET6;\n\taddr.sin6_port = con_ac.ac_port;\n\tinet_pton(AF_INET6, con_ac.ip_ac, &addr.sin6_addr);\n#else\n\taddr.sin_family = AF_INET;\n\taddr.sin_port = con_ac.ac_port;\n\taddr.sin_addr.s_addr = inet_addr(con_ac.ip_ac);\n#endif\n\twpa_printf(MSG_DEBUG,\"Try connecting to %s:%d\\n\",con_ac.ip_ac, con_ac.ac_port);\n\n#endif\n\n\taddress_size = sizeof(addr);\n\n\twhile(1){\n#if defined(LOCALUDP)\n\t\tsprintf(buffer,\"X%05dconnect\",rn);\n#else\n\t\tsprintf(buffer,\"Xconnect\");\n#endif\n\n\t\tbuffer[0] = CONNECT;\n\t\tsendto(fd_ac, buffer, strlen(buffer), 0, (struct sockaddr *)&addr, address_size);\n\n#if defined(LOCALUDP)\n\t\trecvfrom(fd_ac, buffer, sizeof(buffer), 0, (struct sockaddr *)&local, &address_size);\n#else\n\t\trecvfrom(fd_ac, buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &address_size);\n#endif\n\n\t\tif (buffer[0] == CONNECT_R){\n\t\t\tbreak;\n\t\t}else{\n\t\t\tsleep(0.5);\n\t\t}\n\t}\n\n\treturn fd_ac;\n}\n\n\nvoid wait_capability_from_AC(int fd, void *hapd){\n\tunsigned char buffer[10];\n\tint n;\n\n\tsleep(0.5);\n\n\tdo {\n\n#if defined(LOCALUDP)\n\t\tn = sprintf((char *)buffer, \"X%05d\", rn);\n#else\n\t\tn = sprintf((char *)buffer, \"X\");\n#endif\n\n\t\tbuffer[0] = WANT_GOLIVE;\n\t\tn = sendto(fd, buffer, n, 0, (struct sockaddr *)&addr, address_size);\n\n#if defined(LOCALUDP)\n\t\tn = recvfrom(fd, buffer, 10, 0, (struct sockaddr *)&local, &address_size);\n#else\n\t\tn = recvfrom(fd, buffer, 10, 0, (struct sockaddr *)&addr, &address_size);\n#endif\n\n\t\tif (n<=0) {\n\t\t\tend_ipc(fd);\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (buffer[0]) {\n\t\tcase SET_WTPRINFO:\n\t\t\twpa_printf(MSG_DEBUG,\"SET_WTPRINFO: %02X\\n\",buffer[1]);\n\t\t\tmemcpy( wlan0_capa+8, buffer+1, 1);\n\t\t\tsend_response(fd, SET_WTPRINFO_R, NULL, 0);\n\t\t\tbreak;\n\n\t\tcase SET_RATES:\n\t\t\twpa_printf(MSG_DEBUG,\"SET_RATES: %02X %02X %02X %02X %02X %02X %02X %02X\\n\",\n\t\t\t\t   buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],buffer[8]);\n\t\t\tmemcpy( wlan0_capa, buffer+1, 8);\n\t\t\tsend_response(fd, SET_RATES_R, NULL, 0);\n\t\t\tbreak;\n\n\t\tcase SET_MDC:\n\t\t\twpa_printf(MSG_DEBUG,\"SET_MDC: %02X %02X %02X %02X %02X %02X\\n\",\n\t\t\t\t   buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6]);\n\t\t\tmemcpy( wlan0_capa+9, buffer+1, 6);\n\t\t\tsend_response(fd, SET_MDC_R, NULL, 0);\n\t\t\tbreak;\n\n\t\tcase SET_MAC:\n\t\t\twpa_printf(MSG_DEBUG,\"SET_MAC: %02X %02X %02X %02X %02X %02X\\n\",\n\t\t\t\t   buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6]);\n\t\t\tmemcpy( wlan0_capa+15, buffer+1, 6);\n\t\t\tsend_response(fd, SET_MAC_R, NULL, 0);\n\t\t\tbreak;\n\n\t\tcase GOLIVE:\n\t\t\twpa_printf(MSG_DEBUG,\"GOLIVE:\\n\");\n\t\t\tsend_response(fd, GOLIVE_R, NULL, 0);\n\t\t\tbreak;\n\n\t\tcase HAVE_TO_WAIT:\n\t\t\tsleep(1);\n\t\t\tbreak;\n\n\t\tcase CLOSE:\n\t\t\tend_ipc(fd);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\twpa_printf(MSG_DEBUG,\"Unknow code (%d) received in CONNECTed Fase\\n\",buffer[0]);\n\t\t\tbreak;\n\t\t}\n\t} while (buffer[0] != GOLIVE);\n\n}\n\nint end_ipc(int fd){\n\n\tipc_send_CLOSE_to_AC(fd);\n\tif(fd>=0){\n\t\teloop_unregister_read_sock(fd);\n\t\tif(close(fd)<0 ){\n\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tif(\tfd_con>=0 ){\n\t\tif(close(fd_con)<0 ){\n\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint start_ipc(void *hapd,void *inject_func){\n\tReadConfiguration(&con_ac);\n\twpa_printf(MSG_DEBUG,\"< DISCONNECTED >\\n\");\n\n\tint sockfd = open_socket();\n\twpa_printf(MSG_DEBUG,\"< CONNECTED >\\n\");\n\n\twait_capability_from_AC(sockfd, hapd);\n\twpa_printf(MSG_DEBUG,\"< LIVE >\\n\");\n\n\n\tif(sockfd){\n\t\tif (eloop_register_read_sock(sockfd, recv_request, hapd, inject_func)) {\n\t\t\twpa_printf(MSG_ERROR, \"Clould not register IPC socket start_ipc\");\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\treturn sockfd;\n}\n\n\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/ipc_capwap_ac.h",
    "content": "#ifndef __IPC_CAPWAP_AC_H\n#define __IPC_CAPWAP_AC_H\n\ntypedef void (* WTP_frame_inject)(void *, unsigned char *, int);\n\nvoid ipc_send_80211_to_wtp(int fd, u8 *buf, int len);\nint start_ipc(void *hapd, void *inject_func);\nint end_ipc(int fd);\n\nint capability_is_B();\nint capability_get_num_modes();\nint capability_get_num_channels();\nint capability_get_rates(int *rate_arr);\nvoid capability_get_mac(unsigned char *buf);\nvoid prep_beacon(int fd,struct hostapd_data *hapd,struct wpa_driver_ap_params *params);\n\nvoid ipc_send_DEL_WLAN(int fd);\nvoid ipc_send_add_station(int fd, u8 *buf, int len);\nvoid ipc_send_del_station(int fd, u8 *buf, int len);\n\nvoid send_response(int fd, u8 code, u8 *buf, int len);\n\n#endif\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/ipc_capwap_wtp.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n#include <errno.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <sys/un.h>\n#include \"eloop.h\"\n#include \"utils/includes.h\"\n\n#include \"utils/common.h\"\n#include \"drivers/driver.h\"\n#include \"ap/hostapd.h\"\n#include \"ap/ap_config.h\"\n#include \"ap/ap_drv_ops.h\"\n\n#include \"ipc_capwap_wtp.h\"\n#include \"file_conf_wtp.h\"\n#include \"smac_code.h\"\n\n\n#define MAX_BUF 3000\n\n//#define LOCALUDP\n//#define NETUDP\n//#define NETSEQ\n//#define USEIPV6\n\n\nstruct pre_txq {\n\tunsigned char *buf;\n\tint len;\n\tint free;\n};\n\nstruct queue_qos {\n\tint queue_id;\n\tint cwmin;\n\tint cwmax;\n\tint aifs;\n\tint burst_time;\n};\n\nstruct wlan_state {\n\tint rts;\n\tint frag;\n\tstruct hostapd_freq_params freq_params;\n\tstruct queue_qos que[4];\n};\n\nstruct config_wtp con_wtp;\nunsigned char wlan0_capa[21];\nstruct pre_txq buf_txq[8];\n\n\n\n#if defined(LOCALUDP)\n\tstruct sockaddr_un addr;\n\tstruct sockaddr_un local;\n\tint rn;\n#else\n\t#if defined(USEIPV6)\n\t\tstruct sockaddr_in6 addr;\n\t#else\n\t\tstruct sockaddr_in addr;\n\t#endif\n#endif\n\n\n\nsocklen_t address_size;\nstruct wlan_state wl;\nint fd_con;\nstruct sockaddr_un local, remote;\n\nstatic void send_response(int fd, u8 code, u8 *buf, int len);\nstatic void send_varesponse(int fd, u8 code, const char *fmt, ...)\n\t__attribute__ ((__format__ (__printf__, 3, 4)));\n\nstatic void ipc_send_CLOSE_to_WTP(int fd)\n{\n\tunsigned char cmd[10];\n\n\tsend_response(fd, CLOSE, cmd, 10);\n}\n\nvoid ipc_send_80211_to_ac(int fd, u8 *buf, int len)\n{\n\tsend_response(fd, DATE_TO_AC, buf, len);\n}\n\nstatic void send_varesponse(int fd, u8 code, const char *fmt, ...)\n{\n        va_list args;\n        char    buf[1024];\n\tint     l;\n\n        va_start(args, fmt);\n        l = vsnprintf(buf, sizeof(buf), fmt, args);\n        va_end(args);\n\n\tsend_response(fd, code, (u8 *)buf, l);\n}\n\nstatic void send_response(int fd, u8 code, u8 *buf, int len)\n{\n\tu8 tmp_buf[MAX_BUF];\n\ttmp_buf[0] = code;\n\tint n;\n\n#if defined(LOCALUDP)\n\tsprintf(tmp_buf + 1, \"%05d\", rn);\n\tmemcpy(tmp_buf + 6, buf, len);\n\tn = sendto(fd, tmp_buf, len + 6, 0, (struct sockaddr *)&addr, address_size);\n#else\n\tmemcpy(tmp_buf + 1, buf, len);\n\tn = sendto(fd, tmp_buf, len + 1, 0, (struct sockaddr *)&addr, address_size);\n#endif\n\n\tif ( n < 0 ) {\n\t\tperror(\"send\");\n\t\treturn;\n\t}\n}\n\n/* HANDLE */\n\nstatic void SET_RTS_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tstruct hostapd_data *h = hapd;\n\tchar tmp[MAX_BUF];\n\n\tmemcpy(tmp, buf, len);\n\ttmp[len] = 0;\n\n\tint rts = atoi(tmp);\n\twpa_printf(MSG_DEBUG, \"SER RTS: %d\",rts);\n\n\twl.rts = rts;\n\n\tint ret = hostapd_set_rts(h, rts);\n\n\tsend_varesponse(fd, SET_RTS_R, \"%d\", ret);\n}\n\nstatic void GET_RTS_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tsend_varesponse(fd, GET_RTS_R, \"%d\", wl.rts);\n}\n\n\n\nstatic void SET_FRAG_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tstruct hostapd_data *h = hapd;\n\tchar tmp[MAX_BUF];\n\tmemcpy(tmp,buf,len);\n\ttmp[len] = 0;\n\n\tint frag = atoi(tmp);\n\twpa_printf(MSG_DEBUG, \"SER FRAQ: %d\",frag);\n\twl.frag = frag;\n\n\tint ret = hostapd_set_frag(h, frag);\n\tsend_varesponse(fd, SET_FRAG_R, \"%d\", ret);\n}\n\nstatic void GET_FRAG_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tsend_varesponse(fd, GET_FRAG_R, \"%d\", wl.frag);\n}\n\nstatic void SET_FREQ_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tstruct hostapd_data *h = hapd;\n\tchar str[5][10];\n\n\tint i,j=0;\n\tint cnt = 0;\n\n\tfor(i=0; i<len; i++){\n\t\tif(buf[i]==' '){\n\t\t\tstr[cnt][j] = 0;\n\t\t\tj = 0;\n\t\t\tcnt++;\n\t\t}else{\n\t\t\tstr[cnt][j] = buf[i];\n\t\t\tj++;\n\t\t}\n\t}\n\n\twl.freq_params.freq = atoi(str[0]);\n\twl.freq_params.sec_channel_offset = atoi(str[1]);\n\twl.freq_params.ht_enabled = atoi(str[2]);\n\twl.freq_params.channel = atoi(str[3]);\n\twl.freq_params.mode = atoi(str[4]);\n\n\tint ret = hostapd_set_freq(h, wl.freq_params.mode, wl.freq_params.freq, wl.freq_params.channel,\n\t\t\t\t   wl.freq_params.ht_enabled, wl.freq_params.sec_channel_offset);\n\tsend_varesponse(fd, SET_FREQ_R, \"%d\", ret);\n}\n\nstatic void GET_FREQ_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tsend_varesponse(fd, GET_FREQ_R, \"%d %d %d %d %d\",\n\t\t\twl.freq_params.freq,       wl.freq_params.sec_channel_offset,\n\t\t\twl.freq_params.ht_enabled, wl.freq_params.channel,\n\t\t\twl.freq_params.mode);\n}\n\n\nstatic void add_in_SET_TXQ_handle(u8 *buf, int len)\n{\n\tint i;\n\tfor(i=0; i<8; i++){\n\t\tif( buf_txq[i].free == 0) {\n\n\t\t\tbuf_txq[i].buf = malloc( sizeof(char) * len);\n\t\t\tmemcpy( buf_txq[i].buf, buf, len);\n\t\t\tbuf_txq[i].len = len;\n\t\t\tbuf_txq[i].free = 1;\n\t\t}\n\t}\n}\n\nstatic void SET_TXQ_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tstruct hostapd_data *h = hapd;\n\tchar str[5][10];\n\n\tbuf[len]=0;\n\n\tint i,j=0;\n\tint cnt = 0;\n\n\tfor(i=0; i<len; i++){\n\t\tif(buf[i]==' '){\n\t\t\tstr[cnt][j] = 0;\n\t\t\tj = 0;\n\t\t\tcnt++;\n\t\t}else{\n\t\t\tstr[cnt][j] = buf[i];\n\t\t\tj++;\n\t\t}\n\t}\n\n\twl.que[atoi(str[0])].queue_id = atoi(str[0]);\n\twl.que[atoi(str[0])].cwmin = atoi(str[1]);\n\twl.que[atoi(str[0])].cwmax = atoi(str[2]);\n\twl.que[atoi(str[0])].aifs = atoi(str[3]);\n\twl.que[atoi(str[0])].burst_time = atoi(str[4]);\n\n\tint ret = hostapd_set_tx_queue_params(h, wl.que[atoi(str[0])].queue_id,\n\t\t\t\t\t      wl.que[atoi(str[0])].aifs,\n\t\t\t\t\t      wl.que[atoi(str[0])].cwmin,\n\t\t\t\t\t      wl.que[atoi(str[0])].cwmax,\n\t\t\t\t\t      wl.que[atoi(str[0])].burst_time);\n\n\tsend_varesponse(fd, SET_TXQ_R, \"%d\", ret);\n}\n\nvoid flush_SET_TXQ_handle(int fd, void *hapd)\n{\n\tint i;\n\tfor(i=0; i<8; i++){\n\t\tif( buf_txq[i].free == 1){\n\t\t\tbuf_txq[i].free = 0;\n\t\t\tSET_TXQ_handle(fd, buf_txq[i].buf, buf_txq[i].len, hapd);\n\t\t}\n\t}\n}\n\nstatic void SET_ADDR_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\twpa_printf(MSG_DEBUG, \"ADD ADDR: %02X %02X %02X %02X %02X %02X\",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);\n\tstruct hostapd_data *h = hapd;\n\tstatic  unsigned char sup[4]={ 0x82 ,0x84 ,0x8B ,0x96 };\n\n\thostapd_sta_add(h, buf, ( unsigned short)1, ( unsigned short)33,  sup, 4,\n\t\t\t    (u16)1,\n\t\t\t    NULL,\n\t\t\t    (u32)32931);\n}\n\nvoid DEL_ADDR_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\twpa_printf(MSG_DEBUG, \"DEL ADDR: %02X %02X %02X %02X %02X %02X\",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);\n\tstruct hostapd_data *h = hapd;\n//\tstatic unsigned char sup[4]={ 0x82 ,0x84 ,0x8B ,0x96 };\n\n\thostapd_drv_sta_remove(h, buf);\n}\n\nstatic void DEL_WLAN_handle(int fd, u8 *buf, int len, void *hapd)\n{\n\tstruct hostapd_data *h = hapd;\n\twpa_printf(MSG_DEBUG, \"DEL WLAN\");\n\n\tif ( h->driver->hapd_deinit )\n\t\th->driver->hapd_deinit(h->iface->bss[0]->drv_priv);\n\n\thostapd_interface_free(h->iface);\n\tend_ipc(fd);\n\n\texit(0);\n}\n\nstatic void ADD_WLAN_handle(int fd, u8 *buf, int len, void *hapd, unsigned char *ssid_p, int *ssid_len_p)\n{\n\twpa_printf(MSG_DEBUG, \"ADD WLAN: len:%d\",len);\n\tint k;\n\n\tstruct hostapd_data *h = hapd;\n\n\twpa_printf(MSG_DEBUG, \"Radio ID: %d\",buf[0]);\n\twpa_printf(MSG_DEBUG, \"Wlan ID: %d\",buf[1]);\n\twpa_printf(MSG_DEBUG, \"Flag 1: %02X\",buf[2]);\n\twpa_printf(MSG_DEBUG, \"Flag 2: %02X\",buf[3]);\n\n\twpa_printf(MSG_DEBUG, \"Key Index: %d\",buf[4]);\n\twpa_printf(MSG_DEBUG, \"Key Status: %d\",buf[5]);\n\n\tshort key_len;\n\t*(&key_len + 1) = buf[6];\n\t*(&key_len + 0) = buf[7];\n\n\t//wpa_printf(MSG_DEBUG, \"Keylen: %d\",key_len);\n\n\tunsigned char key[key_len];\n\n\tif(key_len){\n\t\tmemcpy(key, buf+8, key_len);\n\t\t//wpa_printf(MSG_DEBUG, \"Key: %s\",key);\n\n\t\th->conf->ssid.wep.idx = 0;\n\t\th->conf->ssid.wep.len[0] = key_len;\n\t\th->conf->ssid.wep.keys_set = 1;\n\t\th->conf->ssid.security_policy=SECURITY_STATIC_WEP;\n\n\t\tchar tmp_key[128];\n\n\t\tfor(k=0; k<key_len; k++)\n\t\t\ttmp_key[k]=*(buf+8+k);\n\t\th->conf->ssid.wep.key[0] = malloc(128);\n\n\t\tmemcpy(h->conf->ssid.wep.key[0], tmp_key, key_len);\n\t}\n\n\tint key_len_int = (int) key_len;\n\n\t//wpa_printf(MSG_DEBUG, \"key len %d\",key_len_int);\n\n\tint pos_mac_mod = 16 + key_len_int;\n\n\twpa_printf(MSG_DEBUG, \"Mac Mode: %d\",buf[pos_mac_mod]);\n\twpa_printf(MSG_DEBUG, \"Tunnel Mode:  %02X\",buf[17+key_len_int]);\n\twpa_printf(MSG_DEBUG, \"Suppress SSID:  %02X\",buf[18+key_len_int]);\n\n\th->conf->mac_mode = buf[pos_mac_mod];\n\n\tif( buf[18+key_len_int]!=0x00 ){\n\t\tint ssid_len = len - 19 - key_len_int;\n\t\tchar tmp_ssid[33];\n\n\t\twpa_printf(MSG_DEBUG, \"SSID LEN: %d\",ssid_len);\n\n\t\tfor(k=0;k<ssid_len;k++)\n\t\t\ttmp_ssid[k]=*(buf + 19 + key_len_int +k);\n\n\t\t*ssid_len_p = ssid_len;\n\t\tmemcpy(ssid_p, tmp_ssid, ssid_len);\n\n\t\th->conf->ssid.ssid_len = ssid_len;\n\t\tmemcpy(h->conf->ssid.ssid, tmp_ssid, ssid_len);\n\t}\n}\n\n\nstatic void management_recv(int fd, u8 code, u8 *buf, int len, void *hapd, void *inject_func)\n{\n\tswitch (code) {\n\tcase  PING:\n\t\tsend_response(fd, PONG, buf, len);\n\t\tbreak;\n\n\tcase SET_RTS:\n\t\tSET_RTS_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase SET_FRAG:\n\t\tSET_FRAG_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase GET_RTS:\n\t\tGET_RTS_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase GET_FRAG:\n\t\tGET_FRAG_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase SET_FREQ:\n\t\tSET_FREQ_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase GET_FREQ:\n\t\tGET_FREQ_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase SET_TXQ:\n\t\tSET_TXQ_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase DATE_TO_WTP:\n\t\t((WTP_frame_inject)inject_func)(((struct hostapd_data *)hapd)->drv_priv, buf, len);\n\t\tbreak;\n\n\tcase SET_ADDR:\n\t\tSET_ADDR_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase DEL_ADDR:\n\t\tDEL_ADDR_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tcase DEL_WLAN:\n\t\tDEL_WLAN_handle(fd, buf, len, hapd);\n\t\tbreak;\n\n\tdefault:\n\t\twpa_printf(MSG_ERROR, \"ERROR IPC: received unrecognizedcode: %d\",code);\n\t\tbreak;\n\t}\n\n}\n\nstatic void recv_request(int fd, void *hapd, void *inject_func)\n{\n\tunsigned char str[MAX_BUF];\n\n\tint n;\n\n#if defined(LOCALUDP)\n\tn = recvfrom(fd, str, MAX_BUF, 0,(struct sockaddr *)&local, &address_size);\n#else\n\tn = recvfrom(fd, str, MAX_BUF, 0,(struct sockaddr *)&addr, &address_size);\n#endif\n\n\tif (n<=0) {\n\t\tend_ipc(fd);\n\t\treturn;\n\t}\n\tmanagement_recv(fd, str[0], str + 1, n -1, hapd, inject_func);\n}\n\n\n\nstatic int open_socket()\n{\n\twpa_printf(MSG_DEBUG, \"Ip:Port  %s:%d  %s\",con_wtp.ip_wtp,con_wtp.wtp_port,con_wtp.path_unix_socket);\n\n\tint fd_wtp;\n\n\tchar buffer[100];\n\n#if defined(LOCALUDP)\n\tsrand((unsigned)time(0));\n\tfd_wtp = socket(AF_UNIX, SOCK_DGRAM, 0);\n\n#elif defined(NETUDP)\n#if defined(USEIPV6)\n\tfd_wtp = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);\n#else\n\tfd_wtp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n#endif\n\n#else\n#if defined(USEIPV6)\n\tfd_wtp = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);\n#else\n\tfd_wtp = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);\n#endif\n\n#endif\n\n#if defined(LOCALUDP)\n\taddr.sun_family = AF_UNIX;\n\tstrcpy(addr.sun_path, con_wtp.path_unix_socket);\n\n\tlocal.sun_family = AF_UNIX;\n\n\twhile(1){\n\t\trn = rand()%100000;\n\t\tsprintf(local.sun_path, \"%s%05d\", con_wtp.path_unix_socket, rn);\n\n\t\tif (bind(fd_wtp, (struct sockaddr *)&local, strlen(local.sun_path) + sizeof(local.sun_family)) == -1) {\n\t\t\tsleep(1);\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\twpa_printf(MSG_DEBUG, \"Try connecting to %s from %s\",addr.sun_path, local.sun_path);\n\n#else\n#if defined(USEIPV6)\n\taddr.sin6_family = AF_INET6;\n\taddr.sin6_port = con_wtp.wtp_port;\n\tinet_pton(AF_INET6, con_wtp.ip_wtp, &addr.sin6_addr);\n#else\n\taddr.sin_family = AF_INET;\n\taddr.sin_port = con_wtp.wtp_port;\n\taddr.sin_addr.s_addr = inet_addr(con_wtp.ip_wtp);\n#endif\n\twpa_printf(MSG_DEBUG, \"Try connecting to %s:%d\",con_wtp.ip_wtp,con_wtp.wtp_port);\n\n#endif\n\taddress_size =  sizeof(addr);\n\n\twpa_printf(MSG_DEBUG, \"<NON CONNECT>\");\n\n\twhile(1) {\n#if defined(LOCALUDP)\n\t\tsprintf(buffer,\"Z%05dconnect\",rn);\n#else\n\t\tsprintf(buffer,\"Zconnect\");\n#endif\n\n\t\tbuffer[0] = CONNECT;\n\t\tsendto(fd_wtp, buffer, strlen(buffer), 0, (struct sockaddr *)&addr, address_size);\n\t\trecvfrom(fd_wtp, buffer, sizeof(buffer), 0,(struct sockaddr *)&local, &address_size);\n\n\t\tif(buffer[0] == CONNECT_R)\n\t\t\tbreak;\n\n\t\tsleep(1);\n\t}\n\twpa_printf(MSG_DEBUG, \"<CONNECTED>\");\n\n\treturn fd_wtp;\n}\n\nint end_ipc(int fd)\n{\n\twpa_printf(MSG_DEBUG, \"Close IPC\");\n\tipc_send_CLOSE_to_WTP(fd);\n\n\tif(fd>=0){\n\t\teloop_unregister_read_sock(fd);\n\t\tif (close(fd)<0)\n\t\t\treturn -1;\n\t}\n\n\tif(fd_con>=0 ){\n\t\tif(close(fd_con)<0 ){\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic void goto_preconnect(int fd, void *hapd){\n\tunsigned char buf[MAX_BUF];\n\tint n;\n\n\tdo {\n\t\t/* Wait Packet */\n#if defined(LOCALUDP)\n\t\tn = recvfrom(fd, buf, MAX_BUF, 0,(struct sockaddr *)&local, &address_size);\n#else\n\t\tn = recvfrom(fd, buf, MAX_BUF, 0,(struct sockaddr *)&addr, &address_size);\n#endif\n\n\t\tif (n <= 0){\n\t\t\tend_ipc(fd);\n\t\t\treturn;\n\t\t}\n\n\t\tswitch(buf[0]) {\n\t\tcase WTPRINFO:\n\t\t\twpa_printf(MSG_DEBUG, \"Command WTPRINFO in CONNECTED State\");\n\t\t\tsend_response(fd, WTPRINFO_R, wlan0_capa + 8, 1);\n\t\t\tbreak;\n\n\t\tcase GET_RATES:\n\t\t\twpa_printf(MSG_DEBUG, \"Command GET_RATES in CONNECTED State\");\n\t\t\tsend_response(fd, GET_RATES_R, wlan0_capa, 8);\n\t\t\tbreak;\n\n\t\tcase GET_MDC:\n\t\t\twpa_printf(MSG_DEBUG, \"Command GET_MDC in CONNECTED State\");\n\t\t\tsend_response(fd, GET_MDC_R, wlan0_capa + 9, 6);\n\t\t\tbreak;\n\n\t\tcase GET_MAC:\n\t\t\twpa_printf(MSG_DEBUG, \"Command GET_MAC in CONNECTED State\");\n\t\t\tsend_response(fd, GET_MAC_R, wlan0_capa + 15, 6);\n\t\t\tbreak;\n\n\t\tcase GOWAITWLAN:\n\t\t\twpa_printf(MSG_DEBUG, \"Command GOWAITWLAN in CONNECTED State\");\n\t\t\tsend_response(fd, GOWAITWLAN_R, NULL, 0);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\twpa_printf(MSG_DEBUG, \"Unknown Command %d in CONNECTED State\", buf[0]);\n\t\t}\n\t} while (buf[0] != GOWAITWLAN);\n\n\twpa_printf(MSG_DEBUG, \"<WAIT WLAN>\");\n}\n\nstatic void wait_ADD_WLAN(int fd, unsigned char *ssid_p, int *ssid_len_p, void *hapd )\n{\n\tunsigned char buf[MAX_BUF];\n\tint n;\n\n\tdo {\n\t\t/* Wait Packet until recv ADD WLAN */\n#if defined(LOCALUDP)\n\t\tn = recvfrom(fd, buf, MAX_BUF, 0,(struct sockaddr *)&local, &address_size);\n#else\n\t\tn = recvfrom(fd, buf, MAX_BUF, 0,(struct sockaddr *)&addr, &address_size);\n#endif\n\n\t\tif(n<=0){\n\t\t\tend_ipc(fd);\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (buf[0]) {\n\t\tcase ADD_WLAN:\n\t\t\tADD_WLAN_handle(fd, buf+1, n-1, hapd, ssid_p, ssid_len_p);\n\t\t\tbreak;\n\n\t\tcase DEL_WLAN:\n\t\t\tDEL_WLAN_handle(fd, NULL, 0, hapd);\n\t\t\tbreak;\n\n\t\tcase SET_TXQ:\n\t\t\tadd_in_SET_TXQ_handle( buf+1, n-1 );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\twpa_printf(MSG_DEBUG, \"Unknown Command in WAITWLAN State %d\",buf[0]);\n\t\t}\n\t} while (buf[0] != ADD_WLAN);\n\n\twpa_printf(MSG_DEBUG, \"<LIVE>\");\n}\n\nint start_ipc(void *hapd, unsigned char *ssid_p, int *ssid_len_p, void *inject_func, unsigned char *cap_info)\n{\n\tmemcpy( wlan0_capa, cap_info, 21);\n\n\tReadConfiguration(&con_wtp);\n\n\tint sockfd = open_socket();\n\n\tgoto_preconnect(sockfd, hapd);\n\twait_ADD_WLAN(sockfd, ssid_p, ssid_len_p, hapd);\n\n\twl.frag = -1;\n\twl.rts = -1;\n\twl.freq_params.channel = 0;\n\twl.freq_params.ht_enabled = 0;\n\twl.freq_params.mode = 0;\n\twl.freq_params.sec_channel_offset = 0;\n\twl.freq_params.freq = 2452;\n\n\twl.que[0].queue_id = 0;\n\twl.que[0].cwmin = 3;\n\twl.que[0].cwmax = 7;\n\twl.que[0].aifs = 2;\n\n\twl.que[1].queue_id = 1;\n\twl.que[1].cwmin = 7;\n\twl.que[1].cwmax = 15;\n\twl.que[1].aifs = 2;\n\n\twl.que[2].queue_id = 2;\n\twl.que[2].cwmin = 15;\n\twl.que[2].cwmax = 1023;\n\twl.que[2].aifs = 3;\n\n\twl.que[3].queue_id = 3;\n\twl.que[3].cwmin = 31;\n\twl.que[3].cwmax = 1023;\n\twl.que[3].aifs = 7;\n\n\tif(sockfd){\n\t\tif (eloop_register_read_sock(sockfd, recv_request, hapd, inject_func)) {\n\t\t\twpa_printf(MSG_ERROR, \"Clould not register IPC socket start_ipc\");\n\t\t\treturn 0;\n\t\t}\n\t}\n\twpa_printf(MSG_DEBUG, \"SOCKET Created %d\",sockfd);\n\treturn sockfd;\n}\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/ipc_capwap_wtp.h",
    "content": "#ifndef __IPC_CAPWAP_WTP_H\n#define __IPC_CAPWAP_WTP_H\n\ntypedef void (* WTP_frame_inject)(void *, unsigned char *, int);\n\nvoid ipc_send_80211_to_ac(int fd, u8 *buf, int len);\nvoid flush_SET_TXQ_handle(int fd, void *hapd);\nint start_ipc(void *hapd, unsigned char *, int *, void * inject_func, unsigned char *);\nint end_ipc(int fd);\n\n#endif\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/smac_code.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A \t       *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Sotiraq Sima (Sotiraq.Sima@gmail.com)                                         *\n *                                                                                         *\n *******************************************************************************************/\n\n#include <linux/types.h>\n\nenum {\n\tERROR = 0,\n\tCLOSE = 1,\n\n\tPING = 2, //  [2]ping\n\tPONG = 3,//  [3]pong\n\n\tSTART_WLAN = 4,\n\tSTART_WLAN_R = 5,\n\n\tSTOP_WLAN = 6,\n\tSTOP_WLAN_R = 7,\n\n\tSET_FREQ = 8, // FREQ sec_channel_offset ht_enabled channel MODE  ex. \"[8]2462 0 0 11 0\"\n\tSET_FREQ_R = 9, // 0 or 1  ex. \"[9]0\"\n\n\tGET_FREQ = 10, // ex. \"[10]\"\n\tGET_FREQ_R = 11, // ex. \"[11]2462 0 0 11 0\"\n\n\tSET_FRAG = 12, // Typically the range used for fragmentation threshold is 256-2346 (-1 == off) ex. \"[12]2000\"\n\tSET_FRAG_R = 13,// ex. \"[13]0\"\n\n\tGET_FRAG = 14, // ex. \"[14]\"   (-1 == off)\n\tGET_FRAG_R = 15, // ex. \"[15]2000\"\n\n\tSET_BITRATE = 16,\n\tSET_BITRATE_R = 17,\n\n\tGET_BITRATE = 18,\n\tGET_BITRATE_R = 19,\n\n\tSET_RTS = 20, // 0-2347 (-1 == off)  ex. \"[20]100\"  (-1 == off)\n\tSET_RTS_R = 21,// ex. \"[21]0\"\n\n\tGET_RTS = 22, // ex. \"]22]\"  (-1 == off)\n\tGET_RTS_R = 23, // ex. \"[23]100\"\n\n\tSET_TXPOWER = 24,\n\tSET_TXPOWER_R = 25,\n\n\tGET_TXPOWER = 26,\n\tGET_TXPOWER_R = 27,\n\n\t/*\n\t * VO - 0  CWMIN:3  CWMAX:7  AIFS:2\n\t * VI - 1  CWMIN:7  CWMAX:15  AIFS:2\n\t * BE - 2  CWMIN:15  CWMAX:1023  AIFS:3\n\t * BK - 3  CWMIN:15  CWMAX:1023  AIFS:7\n\t */\n\tSET_TXQ = 28,\n\tSET_TXQ_R = 29,\n\n\tGET_TXQ = 30,\n\tGET_TXQ_R = 31,\n\n\tSET_ADDR = 32,\n\tSET_ADDR_R = 33,\n\n\tDEL_ADDR = 34,\n\tDEL_ADDR_R = 35,\n\n\tADD_WLAN = 36,\n\tADD_WLAN_R = 37,\n\n\tDEL_WLAN = 38,\n\tDEL_WLAN_R = 39,\n\n\tWTPRINFO = 40,\n\tWTPRINFO_R = 41,\n\n\tGET_RATES = 42,\n\tGET_RATES_R = 43,\n\n\tGET_MDC = 44,\n\tGET_MDC_R = 45,\n\n\tSET_WTPRINFO = 46,\n\tSET_WTPRINFO_R = 47,\n\n\tSET_RATES = 48,\n\tSET_RATES_R = 49,\n\n\tSET_MDC = 50,\n\tSET_MDC_R = 51,\n\n\tGOLIVE = 52,\n\tGOLIVE_R = 53,\n\n\tWANT_GOLIVE = 54,\n\tHAVE_TO_WAIT = 55,\n\n\tGET_MAC = 56,\n\tGET_MAC_R = 57,\n\n\tSET_MAC = 58,\n\tSET_MAC_R = 59,\n\n\tDATE_TO_WTP = 100,\n\tDATE_TO_AC = 101,\n\n\tCONNECT = 102,\n\tCONNECT_R = 103,\n\n\tGOWAITWLAN = 104,\n\tGOWAITWLAN_R = 105\n};\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/switch_8023_80211.c",
    "content": "#include \"utils/includes.h\"\n\n#include \"utils/common.h\"\n#include \"radius/radius.h\"\n#include \"drivers/driver.h\"\n#include \"common/ieee802_11_defs.h\"\n#include \"common/ieee802_11_common.h\"\n\n\n#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))\n#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))\n#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))\n\n#define TYPE_LEN 2\n#define ETH_ALEN 6\n#define ETH_HLEN 14\n\nint add_8022_header( unsigned char *inbuf, int inlen,  unsigned char *outbuf){\n\n\tint indx = 0;\n\t unsigned char DSAP = 0xAA;\n\t unsigned char SSAP = 0xAA;\n\t unsigned char Control = 0x03;\n\t unsigned char Organ_Code[3] = { 0x00, 0x00, 0x00 }; //Encapsulated Ethernet\n\t unsigned char Type[2] = { 0x88, 0x8E };\n\n\tos_memcpy(outbuf + indx, &DSAP, 1);\n\tindx +=1;\n\n\tos_memcpy(outbuf + indx, &SSAP, 1);\n\tindx +=1;\n\n\tos_memcpy(outbuf + indx, &Control, 1);\n\tindx +=1;\n\n\tos_memcpy(outbuf + indx, Organ_Code, sizeof(Organ_Code));\n\tindx +=sizeof(Organ_Code);\n\n\tos_memcpy(outbuf + indx, Type, sizeof(Type));\n\tindx +=sizeof(Type);\n\n\tos_memcpy(outbuf + indx, inbuf, inlen);\n\tindx += inlen;\n\n\treturn indx;\n}\n\nint add_80211_Data_header( unsigned char *da,  unsigned char *sa,  unsigned char *bssid_add, int toDS, int FromDS,  unsigned char *inbuf, int inlen,  unsigned char *outbuf){\n\tint indx = 0;\n\n\tint encaps_len, skip_header_bytes;\n\tstruct ieee80211_hdr hdr;\n\tu16 fc,ethertype;\n\tos_memset(&hdr,0,sizeof(struct ieee80211_hdr));\n\n\thdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);\n\n\thdr.duration_id = 0;\n\thdr.seq_ctrl = 0;\n\n\tif (toDS == 0 && FromDS == 0) {\n\t\tos_memcpy(hdr.addr1, da, ETH_ALEN);\n\t\tos_memcpy(hdr.addr2, sa, ETH_ALEN);\n\t\tos_memcpy(hdr.addr3, bssid_add, ETH_ALEN);\n\t\tCLEARBIT(hdr.frame_control,8);\n\t\tCLEARBIT(hdr.frame_control,9);\n\n\t}else if (toDS == 1 && FromDS == 0) {\n\t\tos_memcpy(hdr.addr1, bssid_add, ETH_ALEN);\n\t\tos_memcpy(hdr.addr2, sa, ETH_ALEN);\n\t\tos_memcpy(hdr.addr3, da, ETH_ALEN);\n\t\tSETBIT(hdr.frame_control,8);\n\t\tCLEARBIT(hdr.frame_control,9);\n\n\t}else if (toDS == 0 && FromDS == 1) {\n\t\tos_memcpy(hdr.addr1, da, ETH_ALEN);\n\t\tos_memcpy(hdr.addr2, bssid_add, ETH_ALEN);\n\t\tos_memcpy(hdr.addr3, sa, ETH_ALEN);\n\t\tCLEARBIT(hdr.frame_control,8);\n\t\tSETBIT(hdr.frame_control,9);\n\n\t}else{\n\t\twpa_printf(MSG_ERROR, \"ERROR add_80211_Data_header\\n\");\n\t}\n\n\tos_memcpy(outbuf + indx, &hdr, sizeof(hdr));\n\tindx += sizeof(hdr);\n\n\tos_memcpy(outbuf + indx, inbuf, inlen);\n\tindx += inlen;\n\n\treturn indx;\n}\n\nint add_8023_header( unsigned char *mac_src, unsigned char *mac_dst, unsigned char *inbuf, int inlen,  unsigned char *outbuf){\n\tint indx = 0;\n\t unsigned char Type[2] = { 0x08, 0x00 };\n\n\tos_memcpy(outbuf + indx, mac_dst, ETH_ALEN);\n\tindx += ETH_ALEN;\n\n\tos_memcpy(outbuf + indx, mac_src, ETH_ALEN);\n\tindx += ETH_ALEN;\n\n\tos_memcpy(outbuf + indx, Type,  sizeof(Type));\n\tindx +=  sizeof(Type);\n\n\tos_memcpy(outbuf + indx, inbuf, inlen);\n\tindx += inlen;\n\n\treturn indx;\n}\n\nint from_8023_to_80211( unsigned char *inbuffer,int inlen, unsigned char *outbuffer, unsigned char *own_addr){\n\n\tint encaps_len, skip_header_bytes;\n\tint indx=0;\n\tstruct ieee80211_hdr hdr;\n\tu16 fc,ethertype;\n\tos_memset(&hdr,0,sizeof(struct ieee80211_hdr));\n\n\thdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);\n\thdr.duration_id = 0;\n\thdr.seq_ctrl = 0;\n\n\tos_memcpy(hdr.addr1, inbuffer, ETH_ALEN);\n\tos_memcpy(hdr.addr2, own_addr, ETH_ALEN);\n\tos_memcpy(hdr.addr3, inbuffer + ETH_ALEN, ETH_ALEN);\n\tCLEARBIT(hdr.frame_control,8);\n\tSETBIT(hdr.frame_control,9);\n\n\tos_memcpy(outbuffer + indx,&hdr,sizeof(hdr));\n\tindx += sizeof(hdr);\n\tos_memcpy(outbuffer + indx, inbuffer, inlen);\n\tindx += inlen;\n\n\treturn indx;\n}\n\nint from_80211_to_8023( unsigned char *inbuffer,int inlen, unsigned char *outbuffer){\n\n\tint hlen_80211 = 24;\n\tmemcpy(outbuffer, inbuffer + hlen_80211, inlen - hlen_80211);\n\treturn inlen - hlen_80211;\n\n}\n"
  },
  {
    "path": "hostapd_wrapper/src/capwap/switch_8023_80211.h",
    "content": "\nint add_8022_header( unsigned char *inbuf, int inlen,  unsigned char *outbuf);\n\nint add_8023_header( unsigned char *mac_src, unsigned char *mac_dst, unsigned char *inbuf, int inlen,  unsigned char *outbuf);\n\nint add_80211_Data_header( unsigned char *da,  unsigned char *sa,  unsigned char *bssid_add, int toDS, int FromDS,  unsigned char *inbuf, int inlen,  unsigned char *outbuf);\n\nint from_8023_to_80211( unsigned char *inbuffer,int inlen, unsigned char *outbuffer, unsigned char *own_addr);\n\nint from_80211_to_8023( unsigned char *inbuffer,int inlen, unsigned char *outbuffer);\n"
  },
  {
    "path": "hostapd_wrapper/src/drivers/driver_capwap.c",
    "content": "/*\n * Driver interaction with Linux capwap/cfg80211\n * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>\n * Copyright (c) 2003-2004, Instant802 Networks, Inc.\n * Copyright (c) 2005-2006, Devicescape Software, Inc.\n * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>\n * Copyright (c) 2009-2010, Atheros Communications\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n\n#include \"includes.h\"\n#include <sys/ioctl.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <net/if.h>\n#include <netlink/genl/genl.h>\n#include <netlink/genl/family.h>\n#include <netlink/genl/ctrl.h>\n#include <linux/rtnetlink.h>\n#include <netpacket/packet.h>\n#include <linux/filter.h>\n#include <string.h>\n#include <unistd.h>\n#include <stdio.h>\n#include <sys/socket.h>\n#include <netinet/ip.h>\n#include <netinet/ip_icmp.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <netdb.h>\n#include \"nl80211_copy.h\"\n\n\n#include \"common.h\"\n#include \"eloop.h\"\n#include \"utils/list.h\"\n#include \"common/ieee802_11_defs.h\"\n#include \"common/ieee802_11_common.h\"\n#include \"l2_packet/l2_packet.h\"\n\n/* CAPWAP */\n#include \"netlink_fake.h\"\n#include \"linux_ioctl_fake.h\"\n#include \"capwap/capwap_mgmt_frame_ac.h\"\n#include \"capwap/ipc_capwap_ac.h\"\n\n#include \"radiotap.h\"\n#include \"radiotap_iter.h\"\n#include \"rfkill.h\"\n#include \"driver.h\"\n\nstruct priv_params params;\n\n\n#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))\n#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))\n#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))\n\n\n#define BUFFER_SIZE 65000\n\nstruct ac_info {\n\tchar *pseudo_interface;\n\tchar *eth_interface;\n\tunsigned char own_mac_addr[ETH_ALEN];\n\tint fd_ipc;\n};\n\nstruct ac_info generic_ac_info;\nvoid AC_inject_frame_in_hostapd(void *priv, u8 *buf, int len);\n\n#ifdef CONFIG_LIBNL20\n/* libnl 2.0 compatibility code */\n#define nl_handle nl_sock\n#define capwap_handle_alloc nl_socket_alloc_cb\n#define capwap_handle_destroy nl_socket_free\n#else\n/*\n * libnl 1.1 has a bug, it tries to allocate socket numbers densely\n * but when you free a socket again it will mess up its bitmap and\n * and use the wrong number the next time it needs a socket ID.\n * Therefore, we wrap the handle alloc/destroy and add our own pid\n * accounting.\n */\nstatic uint32_t port_bitmap[32] = { 0 };\n\n\nstatic struct nl_handle *capwap_handle_alloc(void *cb){\n\tstruct nl_handle *handle;\n\tuint32_t pid = getpid() & 0x3FFFFF;\n\tint i;\n\n\thandle = nl_handle_alloc_cb(cb);\n\n\tfor (i = 0; i < 1024; i++) {\n\t\tif (port_bitmap[i / 32] & (1 << (i % 32)))\n\t\t\tcontinue;\n\t\tport_bitmap[i / 32] |= 1 << (i % 32);\n\t\tpid += i << 22;\n\t\tbreak;\n\t}\n\n\tnl_socket_set_local_port(handle, pid);\n\n\treturn handle;\n}\n\nstatic void capwap_handle_destroy(struct nl_handle *handle)\n{\n\tuint32_t port = nl_socket_get_local_port(handle);\n\n\tport >>= 22;\n\tport_bitmap[port / 32] &= ~(1 << (port % 32));\n\n\tnl_handle_destroy(handle);\n}\n\nstatic inline int __genl_ctrl_alloc_cache(struct nl_handle *h,\n\t\t\t\t\t  struct nl_cache **cache)\n{\n\tstruct nl_cache *tmp = genl_ctrl_alloc_cache(h);\n\tif (!tmp)\n\t\treturn -ENOMEM;\n\t*cache = tmp;\n\treturn 0;\n}\n#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache\n#endif /* CONFIG_LIBNL20 */\n\n\nstruct capwap_handles {\n\tstruct nl_handle *handle;\n\tstruct nl_cache *cache;\n};\n\n\nstatic int nl_create_handles(struct capwap_handles *handles, struct nl_cb *cb,\n\t\t\t     const char *dbg)\n{\n\n\tif (!handles)\n\t\treturn -1;\n\n\thandles->handle = capwap_handle_alloc(cb);\n\n\tif (handles->handle == NULL) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate netlink \"\n\t\t\t   \"callbacks (%s)\", dbg);\n\t\treturn -1;\n\t}\n\n\tif (genl_connect(handles->handle)) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to connect to generic \"\n\t\t\t   \"netlink (%s)\", dbg);\n\t\tgoto err;\n\t}\n\n\tif (genl_ctrl_alloc_cache(handles->handle, &handles->cache) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate generic \"\n\t\t\t   \"netlink cache (%s)\", dbg);\n\t\tgoto err;\n\t}\n\n\treturn 0;\nerr:\n\tcapwap_handle_destroy(handles->handle);\n\treturn -1;\n\n}\n\n\nstatic void nl_destroy_handles(struct capwap_handles *handles)\n{\n\tif (handles->handle == NULL)\n\t\treturn;\n\tnl_cache_free(handles->cache);\n\tcapwap_handle_destroy(handles->handle);\n\thandles->handle = NULL;\n}\n\n\n#ifndef IFF_LOWER_UP\n#define IFF_LOWER_UP   0x10000         /* driver signals L1 up         */\n#endif\n#ifndef IFF_DORMANT\n#define IFF_DORMANT    0x20000         /* driver signals dormant       */\n#endif\n\n#ifndef IF_OPER_DORMANT\n#define IF_OPER_DORMANT 5\n#endif\n#ifndef IF_OPER_UP\n#define IF_OPER_UP 6\n#endif\n\nstruct capwap_global {\n\tstruct dl_list interfaces;\n\tint if_add_ifindex;\n\tstruct netlink_data *netlink;\n\tstruct nl_cb *nl_cb;\n\tstruct capwap_handles nl;\n\tstruct genl_family *capwap;\n\tint ioctl_sock; /* socket for ioctl() use */\n};\n\nstatic void capwap_global_deinit(void *priv);\nstatic void wpa_driver_capwap_deinit(void *priv);\n\nstruct i802_bss {\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct i802_bss *next;\n\tint ifindex;\n\tchar ifname[IFNAMSIZ + 1];\n\tchar brname[IFNAMSIZ];\n\tunsigned int beacon_set:1;\n\tunsigned int added_if_into_bridge:1;\n\tunsigned int added_bridge:1;\n};\n\nstruct wpa_driver_capwap_data {\n\tstruct capwap_global *global;\n\tstruct dl_list list;\n\tu8 addr[ETH_ALEN];\n\tchar phyname[32];\n\tvoid *ctx;\n\tint ifindex;\n\tint if_removed;\n\tint if_disabled;\n\tint ignore_if_down_event;\n\tstruct rfkill_data *rfkill;\n\tstruct wpa_driver_capa capa;\n\tint has_capability;\n\n\tint operstate;\n\n\tint scan_complete_events;\n\n\tstruct capwap_handles nl_event, nl_preq;\n\n\tu8 auth_bssid[ETH_ALEN];\n\tu8 bssid[ETH_ALEN];\n\tint associated;\n\tu8 ssid[32];\n\tsize_t ssid_len;\n\tenum nl80211_iftype nlmode;\n\tenum nl80211_iftype ap_scan_as_station;\n\tunsigned int assoc_freq;\n\n\tint monitor_sock;\n\tint monitor_ifidx;\n\tint no_monitor_iface_capab;\n\n\tunsigned int disabled_11b_rates:1;\n\tunsigned int pending_remain_on_chan:1;\n\tunsigned int in_interface_list:1;\n\n\tu64 remain_on_chan_cookie;\n\tu64 send_action_cookie;\n\n\tunsigned int last_mgmt_freq;\n\tunsigned int ap_oper_freq;\n\n\tstruct wpa_driver_scan_filter *filter_ssids;\n\tsize_t num_filter_ssids;\n\n\tstruct i802_bss first_bss;\n\n#ifdef CONFIG_AP\n\tstruct l2_packet_data *l2;\n#endif /* CONFIG_AP */\n\n#ifdef HOSTAPD\n\tint eapol_sock; /* socket for EAPOL frames */\n\n\tint default_if_indices[16];\n\tint *if_indices;\n\tint num_if_indices;\n\n\tint last_freq;\n\tint last_freq_ht;\n#endif /* HOSTAPD */\n};\n\n\nstatic void wpa_driver_capwap_scan_timeout(void *eloop_ctx,\n\t\t\t\t\t    void *timeout_ctx);\nstatic int wpa_driver_capwap_set_mode(struct i802_bss *bss,\n\t\t\t\t       enum nl80211_iftype nlmode);\nstatic int\nwpa_driver_capwap_finish_drv_init(struct wpa_driver_capwap_data *drv);\nstatic int wpa_driver_capwap_mlme(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   const u8 *addr, int cmd, u16 reason_code,\n\t\t\t\t   int local_state_change);\nstatic void capwap_remove_monitor_interface(\n\tstruct wpa_driver_capwap_data *drv);\nstatic int capwap_send_frame_cmd(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  unsigned int freq, unsigned int wait,\n\t\t\t\t  const u8 *buf, size_t buf_len, u64 *cookie,\n\t\t\t\t  int no_cck);\nstatic int wpa_driver_capwap_probe_req_report(void *priv, int report);\n\n#ifdef HOSTAPD\nstatic void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\nstatic void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\nstatic int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\nstatic int wpa_driver_capwap_if_remove(void *priv,\n\t\t\t\t\tenum wpa_driver_if_type type,\n\t\t\t\t\tconst char *ifname);\n#else /* HOSTAPD */\nstatic inline void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n}\n\nstatic inline void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n}\n\nstatic inline int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n\treturn 0;\n}\n#endif /* HOSTAPD */\n\nstatic int i802_set_freq(void *priv, struct hostapd_freq_params *freq);\nstatic int capwap_disable_11b_rates(struct wpa_driver_capwap_data *drv,\n\t\t\t\t     int ifindex, int disabled);\n\nstatic int capwap_leave_ibss(struct wpa_driver_capwap_data *drv);\n\n\nstatic int is_ap_interface(enum nl80211_iftype nlmode)\n{\n\treturn (nlmode == NL80211_IFTYPE_AP ||\n\t\tnlmode == NL80211_IFTYPE_P2P_GO);\n}\n\n\nstatic int is_sta_interface(enum nl80211_iftype nlmode)\n{\n\treturn (nlmode == NL80211_IFTYPE_STATION ||\n\t\tnlmode == NL80211_IFTYPE_P2P_CLIENT);\n}\n\n\nstatic int is_p2p_interface(enum nl80211_iftype nlmode)\n{\n\treturn (nlmode == NL80211_IFTYPE_P2P_CLIENT ||\n\t\tnlmode == NL80211_IFTYPE_P2P_GO);\n}\n\n\nstruct capwap_bss_info_arg {\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct wpa_scan_results *res;\n\tunsigned int assoc_freq;\n\tu8 assoc_bssid[ETH_ALEN];\n};\n\nstatic int bss_info_handler(struct nl_msg *msg, void *arg);\n\n\n/* capwap code */\nstatic int ack_handler(struct nl_msg *msg, void *arg)\n{\n\tint *err = arg;\n\t*err = 0;\n\treturn NL_STOP;\n}\n\nstatic int finish_handler(struct nl_msg *msg, void *arg)\n{\n\tint *ret = arg;\n\t*ret = 0;\n\treturn NL_SKIP;\n}\n\nstatic int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,\n\t\t\t void *arg)\n{\n\tint *ret = arg;\n\t*ret = err->error;\n\treturn NL_SKIP;\n}\n\n\nstatic int no_seq_check(struct nl_msg *msg, void *arg)\n{\n\treturn NL_OK;\n}\n\n\nstatic int send_and_recv(struct wpa_driver_capwap_data *drv,\n\t\t\t struct nl_handle *nl_handle, struct nl_msg *msg,\n\t\t\t int (*valid_handler)(struct nl_msg *, void *),\n\t\t\t void *valid_data)\n{\n\n\tstruct nl_cb *cb;\n\tint err = -ENOMEM;\n\n\tcb = nl_cb_clone(drv->global->nl_cb);\n\tif (!cb)\n\t\tgoto out;\n\n\terr = nl_send_auto_complete(nl_handle, msg);\n\tif (err < 0)\n\t\tgoto out;\n\n\terr = 1;\n\n\tnl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);\n\tnl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);\n\tnl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);\n\n\tif (valid_handler)\n\t\tnl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,\n\t\t\t  valid_handler, valid_data);\n\n\twhile (err > 0)\n\t\tnl_recvmsgs(nl_handle, cb);\n\n out:\n\n\tnl_cb_put(cb);\n\tnlmsg_free(msg);\n\treturn err;\n}\n\n\nstatic int send_and_recv_msgs(struct wpa_driver_capwap_data *drv,\n\t\t\t      struct nl_msg *msg,\n\t\t\t      int (*valid_handler)(struct nl_msg *, void *),\n\t\t\t      void *valid_data)\n{\n\n\treturn send_and_recv(drv, drv->global->nl.handle, msg, valid_handler,\n\t\t\t     valid_data);\n}\n\n\nstruct family_data {\n\tconst char *group;\n\tint id;\n};\n\n\nstatic int family_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct family_data *res = arg;\n\tstruct nlattr *tb[CTRL_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *mcgrp;\n\tint i;\n\n\tnla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb[CTRL_ATTR_MCAST_GROUPS])\n\t\treturn NL_SKIP;\n\n\tnla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {\n\t\tstruct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];\n\t\tnla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),\n\t\t\t  nla_len(mcgrp), NULL);\n\t\tif (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||\n\t\t    !tb2[CTRL_ATTR_MCAST_GRP_ID] ||\n\t\t    os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),\n\t\t\t       res->group,\n\t\t\t       nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)\n\t\t\tcontinue;\n\t\tres->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);\n\t\tbreak;\n\t};\n\n\treturn NL_SKIP;\n}\n\n\nstatic int nl_get_multicast_id(struct wpa_driver_capwap_data *drv,\n\t\t\t       const char *family, const char *group)\n{\n\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\tstruct family_data res = { group, -ENOENT };\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tgenlmsg_put(msg, 0, 0,\n\t\t    genl_ctrl_resolve(drv->global->nl.handle, \"nlctrl\"),\n\t\t    0, 0, CTRL_CMD_GETFAMILY, 0);\n\tNLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);\n\n\tret = send_and_recv_msgs(drv, msg, family_handler, &res);\n\tmsg = NULL;\n\tif (ret == 0)\n\t\tret = res.id;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic void * capwap_cmd(struct wpa_driver_capwap_data *drv,\n\t\t\t  struct nl_msg *msg, int flags, uint8_t cmd)\n{\n\treturn NULL;\n\treturn genlmsg_put(msg, 0, 0, genl_family_get_id(drv->global->capwap),\n\t\t\t   0, flags, cmd, 0);\n}\n\n\nstatic int wpa_driver_capwap_get_bssid(void *priv, u8 *bssid)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!drv->associated)\n\t\treturn -1;\n\tos_memcpy(bssid, drv->bssid, ETH_ALEN);\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_get_ssid(void *priv, u8 *ssid)\n{\n\twpa_printf(MSG_DEBUG,\"> wpa_driver_capwap_get_ssid\");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!drv->associated)\n\t\treturn -1;\n\tos_memcpy(ssid, drv->ssid, drv->ssid_len);\n\treturn drv->ssid_len;\n}\n\n\nstatic void wpa_driver_capwap_event_link(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t  char *buf, size_t len, int del)\n{\n\n\tunion wpa_event_data event;\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (len > sizeof(event.interface_status.ifname))\n\t\tlen = sizeof(event.interface_status.ifname) - 1;\n\tos_memcpy(event.interface_status.ifname, buf, len);\n\tevent.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :\n\t\tEVENT_INTERFACE_ADDED;\n\n\twpa_printf(MSG_DEBUG, \"RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s\",\n\t\t   del ? \"DEL\" : \"NEW\",\n\t\t   event.interface_status.ifname,\n\t\t   del ? \"removed\" : \"added\");\n\n\tif (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) {\n\t\tif (del) {\n\t\t\tif (drv->if_removed) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: if_removed \"\n\t\t\t\t\t   \"already set - ignore event\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdrv->if_removed = 1;\n\t\t} else {\n\t\t\tif (if_nametoindex(drv->first_bss.ifname) == 0) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Interface %s \"\n\t\t\t\t\t   \"does not exist - ignore \"\n\t\t\t\t\t   \"RTM_NEWLINK\",\n\t\t\t\t\t   drv->first_bss.ifname);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!drv->if_removed) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: if_removed \"\n\t\t\t\t\t   \"already cleared - ignore event\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdrv->if_removed = 0;\n\t\t}\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);\n}\n\n\nstatic int wpa_driver_capwap_own_ifname(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t u8 *buf, size_t len)\n{\n\n\tint attrlen, rta_len;\n\tstruct rtattr *attr;\n\n\tattrlen = len;\n\tattr = (struct rtattr *) buf;\n\n\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n\twhile (RTA_OK(attr, attrlen)) {\n\t\tif (attr->rta_type == IFLA_IFNAME) {\n\t\t\tif (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname)\n\t\t\t    == 0)\n\t\t\t\treturn 1;\n\t\t\telse\n\t\t\t\tbreak;\n\t\t}\n\t\tattr = RTA_NEXT(attr, attrlen);\n\t}\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_own_ifindex(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t  int ifindex, u8 *buf, size_t len)\n{\n\n\tif (drv->ifindex == ifindex)\n\t\treturn 1;\n\n\tif (drv->if_removed && wpa_driver_capwap_own_ifname(drv, buf, len)) {\n\t\tdrv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Update ifindex for a removed \"\n\t\t\t   \"interface\");\n\t\twpa_driver_capwap_finish_drv_init(drv);\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\n\nstatic struct wpa_driver_capwap_data *\ncapwap_find_drv(struct capwap_global *global, int idx, u8 *buf, size_t len)\n{\n\tstruct wpa_driver_capwap_data *drv;\n\tdl_list_for_each(drv, &global->interfaces,\n\t\t\t struct wpa_driver_capwap_data, list) {\n\t\tif (wpa_driver_capwap_own_ifindex(drv, idx, buf, len) ||\n\t\t    have_ifidx(drv, idx))\n\t\t\treturn drv;\n\t}\n\treturn NULL;\n}\n\n\nstatic void wpa_driver_capwap_event_rtm_newlink(void *ctx,\n\t\t\t\t\t\t struct ifinfomsg *ifi,\n\t\t\t\t\t\t u8 *buf, size_t len)\n{\n\n\tstruct capwap_global *global = ctx;\n\tstruct wpa_driver_capwap_data *drv;\n\tint attrlen, rta_len;\n\tstruct rtattr *attr;\n\tu32 brid = 0;\n\tchar namebuf[IFNAMSIZ];\n\n\tdrv = capwap_find_drv(global, ifi->ifi_index, buf, len);\n\tif (!drv) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore event for foreign \"\n\t\t\t   \"ifindex %d\", ifi->ifi_index);\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"RTM_NEWLINK: operstate=%d ifi_flags=0x%x \"\n\t\t   \"(%s%s%s%s)\",\n\t\t   drv->operstate, ifi->ifi_flags,\n\t\t   (ifi->ifi_flags & IFF_UP) ? \"[UP]\" : \"\",\n\t\t   (ifi->ifi_flags & IFF_RUNNING) ? \"[RUNNING]\" : \"\",\n\t\t   (ifi->ifi_flags & IFF_LOWER_UP) ? \"[LOWER_UP]\" : \"\",\n\t\t   (ifi->ifi_flags & IFF_DORMANT) ? \"[DORMANT]\" : \"\");\n\n\tif (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {\n\t\tif (if_indextoname(ifi->ifi_index, namebuf) &&\n\t\t    linux_iface_up(drv->global->ioctl_sock,\n\t\t\t\t   drv->first_bss.ifname) > 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface down \"\n\t\t\t\t   \"event since interface %s is up\", namebuf);\n\t\t\treturn;\n\t\t}\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface down\");\n\t\tif (drv->ignore_if_down_event) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface down \"\n\t\t\t\t   \"event generated by mode change\");\n\t\t\tdrv->ignore_if_down_event = 0;\n\t\t} else {\n\t\t\tdrv->if_disabled = 1;\n\t\t\twpa_supplicant_event(drv->ctx,\n\t\t\t\t\t     EVENT_INTERFACE_DISABLED, NULL);\n\t\t}\n\t}\n\n\tif (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {\n\t\tif (if_indextoname(ifi->ifi_index, namebuf) &&\n\t\t    linux_iface_up(drv->global->ioctl_sock,\n\t\t\t\t   drv->first_bss.ifname) == 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n\t\t\t\t   \"event since interface %s is down\",\n\t\t\t\t   namebuf);\n\t\t} else if (if_nametoindex(drv->first_bss.ifname) == 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n\t\t\t\t   \"event since interface %s does not exist\",\n\t\t\t\t   drv->first_bss.ifname);\n\t\t} else if (drv->if_removed) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n\t\t\t\t   \"event since interface %s is marked \"\n\t\t\t\t   \"removed\", drv->first_bss.ifname);\n\t\t} else {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Interface up\");\n\t\t\tdrv->if_disabled = 0;\n\t\t\twpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,\n\t\t\t\t\t     NULL);\n\t\t}\n\t}\n\n\t/*\n\t * Some drivers send the association event before the operup event--in\n\t * this case, lifting operstate in wpa_driver_capwap_set_operstate()\n\t * fails. This will hit us when wpa_supplicant does not need to do\n\t * IEEE 802.1X authentication\n\t */\n\tif (drv->operstate == 1 &&\n\t    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&\n\t    !(ifi->ifi_flags & IFF_RUNNING))\n\t\tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,\n\t\t\t\t       -1, IF_OPER_UP);\n\n\tattrlen = len;\n\tattr = (struct rtattr *) buf;\n\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n\twhile (RTA_OK(attr, attrlen)) {\n\t\tif (attr->rta_type == IFLA_IFNAME) {\n\t\t\twpa_driver_capwap_event_link(\n\t\t\t\tdrv,\n\t\t\t\t((char *) attr) + rta_len,\n\t\t\t\tattr->rta_len - rta_len, 0);\n\t\t} else if (attr->rta_type == IFLA_MASTER)\n\t\t\tbrid = nla_get_u32((struct nlattr *) attr);\n\t\tattr = RTA_NEXT(attr, attrlen);\n\t}\n\n\tif (ifi->ifi_family == AF_BRIDGE && brid) {\n\t\t/* device has been added to bridge */\n\t\tif_indextoname(brid, namebuf);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Add ifindex %u for bridge %s\",\n\t\t\t   brid, namebuf);\n\t\tadd_ifidx(drv, brid);\n\t}\n}\n\n\nstatic void wpa_driver_capwap_event_rtm_dellink(void *ctx,\n\t\t\t\t\t\t struct ifinfomsg *ifi,\n\t\t\t\t\t\t u8 *buf, size_t len)\n{\n\tstruct capwap_global *global = ctx;\n\tstruct wpa_driver_capwap_data *drv;\n\tint attrlen, rta_len;\n\tstruct rtattr *attr;\n\tu32 brid = 0;\n\n\tdrv = capwap_find_drv(global, ifi->ifi_index, buf, len);\n\tif (!drv) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore dellink event for \"\n\t\t\t   \"foreign ifindex %d\", ifi->ifi_index);\n\t\treturn;\n\t}\n\n\tattrlen = len;\n\tattr = (struct rtattr *) buf;\n\n\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n\twhile (RTA_OK(attr, attrlen)) {\n\t\tif (attr->rta_type == IFLA_IFNAME) {\n\t\t\twpa_driver_capwap_event_link(\n\t\t\t\tdrv,\n\t\t\t\t((char *) attr) + rta_len,\n\t\t\t\tattr->rta_len - rta_len, 1);\n\t\t} else if (attr->rta_type == IFLA_MASTER)\n\t\t\tbrid = nla_get_u32((struct nlattr *) attr);\n\t\tattr = RTA_NEXT(attr, attrlen);\n\t}\n\n\tif (ifi->ifi_family == AF_BRIDGE && brid) {\n\t\t/* device has been removed from bridge */\n\t\tchar namebuf[IFNAMSIZ];\n\t\tif_indextoname(brid, namebuf);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Remove ifindex %u for bridge \"\n\t\t\t   \"%s\", brid, namebuf);\n\t\tdel_ifidx(drv, brid);\n\t}\n}\n\n\nstatic void mlme_event_auth(struct wpa_driver_capwap_data *drv,\n\t\t\t    const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len < 24 + sizeof(mgmt->u.auth)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Too short association event \"\n\t\t\t   \"frame\");\n\t\treturn;\n\t}\n\n\tos_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);\n\tos_memset(&event, 0, sizeof(event));\n\tos_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);\n\tevent.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);\n\tevent.auth.status_code = le_to_host16(mgmt->u.auth.status_code);\n\tif (len > 24 + sizeof(mgmt->u.auth)) {\n\t\tevent.auth.ies = mgmt->u.auth.variable;\n\t\tevent.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);\n}\n\n\nstatic unsigned int capwap_get_assoc_freq(struct wpa_driver_capwap_data *drv)\n{\n\n\tstruct nl_msg *msg;\n\tint ret;\n\tstruct capwap_bss_info_arg arg;\n\n\tos_memset(&arg, 0, sizeof(arg));\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\targ.drv = drv;\n\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Operating frequency for the \"\n\t\t\t   \"associated BSS from scan results: %u MHz\",\n\t\t\t   arg.assoc_freq);\n\t\treturn arg.assoc_freq ? arg.assoc_freq : drv->assoc_freq;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n\t\t   \"(%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn drv->assoc_freq;\n}\n\n\nstatic void mlme_event_assoc(struct wpa_driver_capwap_data *drv,\n\t\t\t    const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tu16 status;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len < 24 + sizeof(mgmt->u.assoc_resp)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Too short association event \"\n\t\t\t   \"frame\");\n\t\treturn;\n\t}\n\n\tstatus = le_to_host16(mgmt->u.assoc_resp.status_code);\n\tif (status != WLAN_STATUS_SUCCESS) {\n\t\tos_memset(&event, 0, sizeof(event));\n\t\tevent.assoc_reject.bssid = mgmt->bssid;\n\t\tif (len > 24 + sizeof(mgmt->u.assoc_resp)) {\n\t\t\tevent.assoc_reject.resp_ies =\n\t\t\t\t(u8 *) mgmt->u.assoc_resp.variable;\n\t\t\tevent.assoc_reject.resp_ies_len =\n\t\t\t\tlen - 24 - sizeof(mgmt->u.assoc_resp);\n\t\t}\n\t\tevent.assoc_reject.status_code = status;\n\n\t\twpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);\n\t\treturn;\n\t}\n\n\tdrv->associated = 1;\n\tos_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (len > 24 + sizeof(mgmt->u.assoc_resp)) {\n\t\tevent.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;\n\t\tevent.assoc_info.resp_ies_len =\n\t\t\tlen - 24 - sizeof(mgmt->u.assoc_resp);\n\t}\n\n\tevent.assoc_info.freq = drv->assoc_freq;\n\n\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);\n}\n\n\nstatic void mlme_event_connect(struct wpa_driver_capwap_data *drv,\n\t\t\t       enum nl80211_commands cmd, struct nlattr *status,\n\t\t\t       struct nlattr *addr, struct nlattr *req_ie,\n\t\t\t       struct nlattr *resp_ie)\n{\n\n\tunion wpa_event_data event;\n\n\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n\t\t/*\n\t\t * Avoid reporting two association events that would confuse\n\t\t * the core code.\n\t\t */\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore connect event (cmd=%d) \"\n\t\t\t   \"when using userspace SME\", cmd);\n\t\treturn;\n\t}\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (cmd == NL80211_CMD_CONNECT &&\n\t    nla_get_u16(status) != WLAN_STATUS_SUCCESS) {\n\t\tif (addr)\n\t\t\tevent.assoc_reject.bssid = nla_data(addr);\n\t\tif (resp_ie) {\n\t\t\tevent.assoc_reject.resp_ies = nla_data(resp_ie);\n\t\t\tevent.assoc_reject.resp_ies_len = nla_len(resp_ie);\n\t\t}\n\t\tevent.assoc_reject.status_code = nla_get_u16(status);\n\t\twpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);\n\t\treturn;\n\t}\n\n\tdrv->associated = 1;\n\tif (addr)\n\t\tos_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);\n\n\tif (req_ie) {\n\t\tevent.assoc_info.req_ies = nla_data(req_ie);\n\t\tevent.assoc_info.req_ies_len = nla_len(req_ie);\n\t}\n\tif (resp_ie) {\n\t\tevent.assoc_info.resp_ies = nla_data(resp_ie);\n\t\tevent.assoc_info.resp_ies_len = nla_len(resp_ie);\n\t}\n\n\tevent.assoc_info.freq = capwap_get_assoc_freq(drv);\n\n\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);\n}\n\n\nstatic void mlme_event_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct nlattr *reason, struct nlattr *addr)\n{\n\tunion wpa_event_data data;\n\n\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n\t\t/*\n\t\t * Avoid reporting two disassociation events that could\n\t\t * confuse the core code.\n\t\t */\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore disconnect \"\n\t\t\t   \"event when using userspace SME\");\n\t\treturn;\n\t}\n\n\tdrv->associated = 0;\n\tos_memset(&data, 0, sizeof(data));\n\tif (reason)\n\t\tdata.disassoc_info.reason_code = nla_get_u16(reason);\n\twpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data);\n}\n\n\nstatic void mlme_timeout_event(struct wpa_driver_capwap_data *drv,\n\t\t\t       enum nl80211_commands cmd, struct nlattr *addr)\n{\n\tunion wpa_event_data event;\n\tenum wpa_event_type ev;\n\n\tif (nla_len(addr) != ETH_ALEN)\n\t\treturn;\n\n\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d; timeout with \" MACSTR,\n\t\t   cmd, MAC2STR((u8 *) nla_data(addr)));\n\n\tif (cmd == NL80211_CMD_AUTHENTICATE)\n\t\tev = EVENT_AUTH_TIMED_OUT;\n\telse if (cmd == NL80211_CMD_ASSOCIATE)\n\t\tev = EVENT_ASSOC_TIMED_OUT;\n\telse\n\t\treturn;\n\n\tos_memset(&event, 0, sizeof(event));\n\tos_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);\n\twpa_supplicant_event(drv->ctx, ev, &event);\n}\n\n\nstatic void mlme_event_mgmt(struct wpa_driver_capwap_data *drv,\n\t\t\t    struct nlattr *freq, const u8 *frame, size_t len)\n{\n\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tu16 fc, stype;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len < 24) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Too short action frame\");\n\t\treturn;\n\t}\n\n\tfc = le_to_host16(mgmt->frame_control);\n\tstype = WLAN_FC_GET_STYPE(fc);\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (freq) {\n\t\tevent.rx_action.freq = nla_get_u32(freq);\n\t\tdrv->last_mgmt_freq = event.rx_action.freq;\n\t}\n\tif (stype == WLAN_FC_STYPE_ACTION) {\n\t\tevent.rx_action.da = mgmt->da;\n\t\tevent.rx_action.sa = mgmt->sa;\n\t\tevent.rx_action.bssid = mgmt->bssid;\n\t\tevent.rx_action.category = mgmt->u.action.category;\n\t\tevent.rx_action.data = &mgmt->u.action.category + 1;\n\t\tevent.rx_action.len = frame + len - event.rx_action.data;\n\t\twpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);\n\t} else {\n\t\tevent.rx_mgmt.frame = frame;\n\t\tevent.rx_mgmt.frame_len = len;\n\t\twpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);\n\t}\n}\n\n\nstatic void mlme_event_action_tx_status(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\tstruct nlattr *cookie, const u8 *frame,\n\t\t\t\t\tsize_t len, struct nlattr *ack)\n{\n\tunion wpa_event_data event;\n\tconst struct ieee80211_hdr *hdr;\n\tu16 fc;\n\tu64 cookie_val;\n\n\tif (!cookie)\n\t\treturn;\n\n\tcookie_val = nla_get_u64(cookie);\n\twpa_printf(MSG_DEBUG, \"capwap: Action TX status: cookie=0%llx%s \"\n\t\t   \"(ack=%d)\",\n\t\t   (long long unsigned int) cookie_val,\n\t\t   cookie_val == drv->send_action_cookie ?\n\t\t   \" (match)\" : \" (unknown)\", ack != NULL);\n\tif (cookie_val != drv->send_action_cookie)\n\t\treturn;\n\n\thdr = (const struct ieee80211_hdr *) frame;\n\tfc = le_to_host16(hdr->frame_control);\n\n\tos_memset(&event, 0, sizeof(event));\n\tevent.tx_status.type = WLAN_FC_GET_TYPE(fc);\n\tevent.tx_status.stype = WLAN_FC_GET_STYPE(fc);\n\tevent.tx_status.dst = hdr->addr1;\n\tevent.tx_status.data = frame;\n\tevent.tx_status.data_len = len;\n\tevent.tx_status.ack = ack != NULL;\n\twpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);\n}\n\n\nstatic void mlme_event_deauth_disassoc(struct wpa_driver_capwap_data *drv,\n\t\t\t\t       enum wpa_event_type type,\n\t\t\t\t       const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tconst u8 *bssid = NULL;\n\tu16 reason_code = 0;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len >= 24) {\n\t\tbssid = mgmt->bssid;\n\n\t\tif (drv->associated != 0 &&\n\t\t    os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&\n\t\t    os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {\n\t\t\t/*\n\t\t\t * We have presumably received this deauth as a\n\t\t\t * response to a clear_state_mismatch() outgoing\n\t\t\t * deauth.  Don't let it take us offline!\n\t\t\t */\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Deauth received \"\n\t\t\t\t   \"from Unknown BSSID \" MACSTR \" -- ignoring\",\n\t\t\t\t   MAC2STR(bssid));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tdrv->associated = 0;\n\tos_memset(&event, 0, sizeof(event));\n\n\t/* Note: Same offset for Reason Code in both frame subtypes */\n\tif (len >= 24 + sizeof(mgmt->u.deauth))\n\t\treason_code = le_to_host16(mgmt->u.deauth.reason_code);\n\n\tif (type == EVENT_DISASSOC) {\n\t\tevent.disassoc_info.addr = bssid;\n\t\tevent.disassoc_info.reason_code = reason_code;\n\t\tif (frame + len > mgmt->u.disassoc.variable) {\n\t\t\tevent.disassoc_info.ie = mgmt->u.disassoc.variable;\n\t\t\tevent.disassoc_info.ie_len = frame + len -\n\t\t\t\tmgmt->u.disassoc.variable;\n\t\t}\n\t} else {\n\t\tevent.deauth_info.addr = bssid;\n\t\tevent.deauth_info.reason_code = reason_code;\n\t\tif (frame + len > mgmt->u.deauth.variable) {\n\t\t\tevent.deauth_info.ie = mgmt->u.deauth.variable;\n\t\t\tevent.deauth_info.ie_len = frame + len -\n\t\t\t\tmgmt->u.deauth.variable;\n\t\t}\n\t}\n\n\twpa_supplicant_event(drv->ctx, type, &event);\n}\n\n\nstatic void mlme_event_unprot_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t enum wpa_event_type type,\n\t\t\t\t\t const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tu16 reason_code = 0;\n\n\tif (len < 24)\n\t\treturn;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\n\tos_memset(&event, 0, sizeof(event));\n\t/* Note: Same offset for Reason Code in both frame subtypes */\n\tif (len >= 24 + sizeof(mgmt->u.deauth))\n\t\treason_code = le_to_host16(mgmt->u.deauth.reason_code);\n\n\tif (type == EVENT_UNPROT_DISASSOC) {\n\t\tevent.unprot_disassoc.sa = mgmt->sa;\n\t\tevent.unprot_disassoc.da = mgmt->da;\n\t\tevent.unprot_disassoc.reason_code = reason_code;\n\t} else {\n\t\tevent.unprot_deauth.sa = mgmt->sa;\n\t\tevent.unprot_deauth.da = mgmt->da;\n\t\tevent.unprot_deauth.reason_code = reason_code;\n\t}\n\n\twpa_supplicant_event(drv->ctx, type, &event);\n}\n\n\nstatic void mlme_event(struct wpa_driver_capwap_data *drv,\n\t\t       enum nl80211_commands cmd, struct nlattr *frame,\n\t\t       struct nlattr *addr, struct nlattr *timed_out,\n\t\t       struct nlattr *freq, struct nlattr *ack,\n\t\t       struct nlattr *cookie)\n{\n\tif (timed_out && addr) {\n\t\tmlme_timeout_event(drv, cmd, addr);\n\t\treturn;\n\t}\n\n\tif (frame == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d without frame \"\n\t\t\t   \"data\", cmd);\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d\", cmd);\n\twpa_hexdump(MSG_MSGDUMP, \"capwap: MLME event frame\",\n\t\t    nla_data(frame), nla_len(frame));\n\n\tswitch (cmd) {\n\tcase NL80211_CMD_AUTHENTICATE:\n\t\tmlme_event_auth(drv, nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_ASSOCIATE:\n\t\tmlme_event_assoc(drv, nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_DEAUTHENTICATE:\n\t\tmlme_event_deauth_disassoc(drv, EVENT_DEAUTH,\n\t\t\t\t\t   nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_DISASSOCIATE:\n\t\tmlme_event_deauth_disassoc(drv, EVENT_DISASSOC,\n\t\t\t\t\t   nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_FRAME:\n\t\tmlme_event_mgmt(drv, freq, nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_FRAME_TX_STATUS:\n\t\tmlme_event_action_tx_status(drv, cookie, nla_data(frame),\n\t\t\t\t\t    nla_len(frame), ack);\n\t\tbreak;\n\tcase NL80211_CMD_UNPROT_DEAUTHENTICATE:\n\t\tmlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,\n\t\t\t\t\t     nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_UNPROT_DISASSOCIATE:\n\t\tmlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,\n\t\t\t\t\t     nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n\nstatic void mlme_event_michael_mic_failure(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t   struct nlattr *tb[])\n{\n\tunion wpa_event_data data;\n\n\twpa_printf(MSG_DEBUG, \"capwap: MLME event Michael MIC failure\");\n\tos_memset(&data, 0, sizeof(data));\n\tif (tb[NL80211_ATTR_MAC]) {\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: Source MAC address\",\n\t\t\t    nla_data(tb[NL80211_ATTR_MAC]),\n\t\t\t    nla_len(tb[NL80211_ATTR_MAC]));\n\t\tdata.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);\n\t}\n\tif (tb[NL80211_ATTR_KEY_SEQ]) {\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: TSC\",\n\t\t\t    nla_data(tb[NL80211_ATTR_KEY_SEQ]),\n\t\t\t    nla_len(tb[NL80211_ATTR_KEY_SEQ]));\n\t}\n\tif (tb[NL80211_ATTR_KEY_TYPE]) {\n\t\tenum nl80211_key_type key_type =\n\t\t\tnla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Key Type %d\", key_type);\n\t\tif (key_type == NL80211_KEYTYPE_PAIRWISE)\n\t\t\tdata.michael_mic_failure.unicast = 1;\n\t} else\n\t\tdata.michael_mic_failure.unicast = 1;\n\n\tif (tb[NL80211_ATTR_KEY_IDX]) {\n\t\tu8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Key Id %d\", key_id);\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);\n}\n\n\nstatic void mlme_event_join_ibss(struct wpa_driver_capwap_data *drv,\n\t\t\t\t struct nlattr *tb[])\n{\n\tif (tb[NL80211_ATTR_MAC] == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No address in IBSS joined \"\n\t\t\t   \"event\");\n\t\treturn;\n\t}\n\tos_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);\n\tdrv->associated = 1;\n\twpa_printf(MSG_DEBUG, \"capwap: IBSS \" MACSTR \" joined\",\n\t\t   MAC2STR(drv->bssid));\n\n\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);\n}\n\n\nstatic void mlme_event_remain_on_channel(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t int cancel_event, struct nlattr *tb[])\n{\n\tunsigned int freq, chan_type, duration;\n\tunion wpa_event_data data;\n\tu64 cookie;\n\n\tif (tb[NL80211_ATTR_WIPHY_FREQ])\n\t\tfreq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);\n\telse\n\t\tfreq = 0;\n\n\tif (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])\n\t\tchan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);\n\telse\n\t\tchan_type = 0;\n\n\tif (tb[NL80211_ATTR_DURATION])\n\t\tduration = nla_get_u32(tb[NL80211_ATTR_DURATION]);\n\telse\n\t\tduration = 0;\n\n\tif (tb[NL80211_ATTR_COOKIE])\n\t\tcookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);\n\telse\n\t\tcookie = 0;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Remain-on-channel event (cancel=%d \"\n\t\t   \"freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))\",\n\t\t   cancel_event, freq, chan_type, duration,\n\t\t   (long long unsigned int) cookie,\n\t\t   cookie == drv->remain_on_chan_cookie ? \"match\" : \"unknown\");\n\n\tif (cookie != drv->remain_on_chan_cookie)\n\t\treturn; /* not for us */\n\n\tif (cancel_event)\n\t\tdrv->pending_remain_on_chan = 0;\n\n\tos_memset(&data, 0, sizeof(data));\n\tdata.remain_on_channel.freq = freq;\n\tdata.remain_on_channel.duration = duration;\n\twpa_supplicant_event(drv->ctx, cancel_event ?\n\t\t\t     EVENT_CANCEL_REMAIN_ON_CHANNEL :\n\t\t\t     EVENT_REMAIN_ON_CHANNEL, &data);\n}\n\n\nstatic void send_scan_event(struct wpa_driver_capwap_data *drv, int aborted,\n\t\t\t    struct nlattr *tb[])\n{\n\tunion wpa_event_data event;\n\tstruct nlattr *nl;\n\tint rem;\n\tstruct scan_info *info;\n#define MAX_REPORT_FREQS 50\n\tint freqs[MAX_REPORT_FREQS];\n\tint num_freqs = 0;\n\n\tos_memset(&event, 0, sizeof(event));\n\tinfo = &event.scan_info;\n\tinfo->aborted = aborted;\n\n\tif (tb[NL80211_ATTR_SCAN_SSIDS]) {\n\t\tnla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {\n\t\t\tstruct wpa_driver_scan_ssid *s =\n\t\t\t\t&info->ssids[info->num_ssids];\n\t\t\ts->ssid = nla_data(nl);\n\t\t\ts->ssid_len = nla_len(nl);\n\t\t\tinfo->num_ssids++;\n\t\t\tif (info->num_ssids == WPAS_MAX_SCAN_SSIDS)\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {\n\t\tnla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)\n\t\t{\n\t\t\tfreqs[num_freqs] = nla_get_u32(nl);\n\t\t\tnum_freqs++;\n\t\t\tif (num_freqs == MAX_REPORT_FREQS - 1)\n\t\t\t\tbreak;\n\t\t}\n\t\tinfo->freqs = freqs;\n\t\tinfo->num_freqs = num_freqs;\n\t}\n\twpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);\n}\n\n\nstatic int get_link_signal(struct nl_msg *msg, void *arg)\n{\n\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];\n\tstatic struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {\n\t\t[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },\n\t};\n\tstruct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];\n\tstatic struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {\n\t\t[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },\n\t\t[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },\n\t\t[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },\n\t\t[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },\n\t};\n\tstruct wpa_signal_info *sig_change = arg;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb[NL80211_ATTR_STA_INFO] ||\n\t    nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_STA_INFO], policy))\n\t\treturn NL_SKIP;\n\tif (!sinfo[NL80211_STA_INFO_SIGNAL])\n\t\treturn NL_SKIP;\n\n\tsig_change->current_signal =\n\t\t(s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);\n\n\tif (sinfo[NL80211_STA_INFO_TX_BITRATE]) {\n\t\tif (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,\n\t\t\t\t     sinfo[NL80211_STA_INFO_TX_BITRATE],\n\t\t\t\t     rate_policy)) {\n\t\t\tsig_change->current_txrate = 0;\n\t\t} else {\n\t\t\tif (rinfo[NL80211_RATE_INFO_BITRATE]) {\n\t\t\t\tsig_change->current_txrate =\n\t\t\t\t\tnla_get_u16(rinfo[\n\t\t\t\t\t     NL80211_RATE_INFO_BITRATE]) * 100;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_get_link_signal(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   struct wpa_signal_info *sig)\n{\n\n\tstruct nl_msg *msg;\n\n\tsig->current_signal = -9999;\n\tsig->current_txrate = 0;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);\n\n\treturn send_and_recv_msgs(drv, msg, get_link_signal, sig);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int get_link_noise(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];\n\tstatic struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {\n\t\t[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },\n\t\t[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },\n\t};\n\tstruct wpa_signal_info *sig_change = arg;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (!tb[NL80211_ATTR_SURVEY_INFO]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: survey data missing!\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_SURVEY_INFO],\n\t\t\t     survey_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: failed to parse nested \"\n\t\t\t   \"attributes!\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])\n\t\treturn NL_SKIP;\n\n\tif (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=\n\t    sig_change->frequency)\n\t\treturn NL_SKIP;\n\n\tif (!sinfo[NL80211_SURVEY_INFO_NOISE])\n\t\treturn NL_SKIP;\n\n\tsig_change->current_noise =\n\t\t(s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_get_link_noise(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct wpa_signal_info *sig_change)\n{\n\n\tstruct nl_msg *msg;\n\n\tsig_change->current_noise = 9999;\n\tsig_change->frequency = drv->assoc_freq;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\treturn send_and_recv_msgs(drv, msg, get_link_noise, sig_change);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int get_noise_for_scan_results(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];\n\tstatic struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {\n\t\t[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },\n\t\t[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },\n\t};\n\tstruct wpa_scan_results *scan_results = arg;\n\tstruct wpa_scan_res *scan_res;\n\tsize_t i;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (!tb[NL80211_ATTR_SURVEY_INFO]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Survey data missing\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_SURVEY_INFO],\n\t\t\t     survey_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to parse nested \"\n\t\t\t   \"attributes\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (!sinfo[NL80211_SURVEY_INFO_NOISE])\n\t\treturn NL_SKIP;\n\n\tif (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])\n\t\treturn NL_SKIP;\n\n\tfor (i = 0; i < scan_results->num; ++i) {\n\t\tscan_res = scan_results->res[i];\n\t\tif (!scan_res)\n\t\t\tcontinue;\n\t\tif ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=\n\t\t    scan_res->freq)\n\t\t\tcontinue;\n\t\tif (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))\n\t\t\tcontinue;\n\t\tscan_res->noise = (s8)\n\t\t\tnla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);\n\t\tscan_res->flags &= ~WPA_SCAN_NOISE_INVALID;\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_get_noise_for_scan_results(\n\tstruct wpa_driver_capwap_data *drv,\n\tstruct wpa_scan_results *scan_res)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\treturn send_and_recv_msgs(drv, msg, get_noise_for_scan_results,\n\t\t\t\t  scan_res);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic void capwap_cqm_event(struct wpa_driver_capwap_data *drv,\n\t\t\t      struct nlattr *tb[])\n{\n\tstatic struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {\n\t\t[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },\n\t\t[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },\n\t};\n\tstruct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];\n\tenum nl80211_cqm_rssi_threshold_event event;\n\tunion wpa_event_data ed;\n\tstruct wpa_signal_info sig;\n\tint res;\n\n\tif (tb[NL80211_ATTR_CQM] == NULL ||\n\t    nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],\n\t\t\t     cqm_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore invalid CQM event\");\n\t\treturn;\n\t}\n\n\tos_memset(&ed, 0, sizeof(ed));\n\n\tif (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {\n\t\tif (!tb[NL80211_ATTR_MAC])\n\t\t\treturn;\n\t\tos_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),\n\t\t\t  ETH_ALEN);\n\t\twpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);\n\t\treturn;\n\t}\n\n\tif (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)\n\t\treturn;\n\tevent = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);\n\n\tif (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Connection quality monitor \"\n\t\t\t   \"event: RSSI high\");\n\t\ted.signal_change.above_threshold = 1;\n\t} else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Connection quality monitor \"\n\t\t\t   \"event: RSSI low\");\n\t\ted.signal_change.above_threshold = 0;\n\t} else\n\t\treturn;\n\n\tres = capwap_get_link_signal(drv, &sig);\n\tif (res == 0) {\n\t\ted.signal_change.current_signal = sig.current_signal;\n\t\ted.signal_change.current_txrate = sig.current_txrate;\n\t\twpa_printf(MSG_DEBUG, \"capwap: Signal: %d dBm  txrate: %d\",\n\t\t\t   sig.current_signal, sig.current_txrate);\n\t}\n\n\tres = capwap_get_link_noise(drv, &sig);\n\tif (res == 0) {\n\t\ted.signal_change.current_noise = sig.current_noise;\n\t\twpa_printf(MSG_DEBUG, \"capwap: Noise: %d dBm\",\n\t\t\t   sig.current_noise);\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);\n}\n\n\nstatic void capwap_new_station_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t      struct nlattr **tb)\n{\n\tu8 *addr;\n\tunion wpa_event_data data;\n\n\tif (tb[NL80211_ATTR_MAC] == NULL)\n\t\treturn;\n\taddr = nla_data(tb[NL80211_ATTR_MAC]);\n\twpa_printf(MSG_DEBUG, \"capwap: New station \" MACSTR, MAC2STR(addr));\n\n\tif (is_ap_interface(drv->nlmode) && drv->no_monitor_iface_capab) {\n\t\tu8 *ies = NULL;\n\t\tsize_t ies_len = 0;\n\t\tif (tb[NL80211_ATTR_IE]) {\n\t\t\ties = nla_data(tb[NL80211_ATTR_IE]);\n\t\t\ties_len = nla_len(tb[NL80211_ATTR_IE]);\n\t\t}\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: Assoc Req IEs\", ies, ies_len);\n\t\tdrv_event_assoc(drv->ctx, addr, ies, ies_len, 0);\n\t\treturn;\n\t}\n\n\tif (drv->nlmode != NL80211_IFTYPE_ADHOC)\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tos_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);\n\twpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);\n}\n\n\nstatic void capwap_del_station_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t      struct nlattr **tb)\n{\n\tu8 *addr;\n\tunion wpa_event_data data;\n\n\tif (tb[NL80211_ATTR_MAC] == NULL)\n\t\treturn;\n\taddr = nla_data(tb[NL80211_ATTR_MAC]);\n\twpa_printf(MSG_DEBUG, \"capwap: Delete station \" MACSTR,\n\t\t   MAC2STR(addr));\n\n\tif (is_ap_interface(drv->nlmode) && drv->no_monitor_iface_capab) {\n\t\tdrv_event_disassoc(drv->ctx, addr);\n\t\treturn;\n\t}\n\n\tif (drv->nlmode != NL80211_IFTYPE_ADHOC)\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tos_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);\n\twpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);\n}\n\n\nstatic void capwap_rekey_offload_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\tstruct nlattr **tb)\n{\n\tstruct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];\n\tstatic struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {\n\t\t[NL80211_REKEY_DATA_KEK] = {\n\t\t\t.minlen = NL80211_KEK_LEN,\n\t\t\t.maxlen = NL80211_KEK_LEN,\n\t\t},\n\t\t[NL80211_REKEY_DATA_KCK] = {\n\t\t\t.minlen = NL80211_KCK_LEN,\n\t\t\t.maxlen = NL80211_KCK_LEN,\n\t\t},\n\t\t[NL80211_REKEY_DATA_REPLAY_CTR] = {\n\t\t\t.minlen = NL80211_REPLAY_CTR_LEN,\n\t\t\t.maxlen = NL80211_REPLAY_CTR_LEN,\n\t\t},\n\t};\n\tunion wpa_event_data data;\n\n\tif (!tb[NL80211_ATTR_MAC])\n\t\treturn;\n\tif (!tb[NL80211_ATTR_REKEY_DATA])\n\t\treturn;\n\tif (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,\n\t\t\t     tb[NL80211_ATTR_REKEY_DATA], rekey_policy))\n\t\treturn;\n\tif (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tdata.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);\n\twpa_printf(MSG_DEBUG, \"capwap: Rekey offload event for BSSID \" MACSTR,\n\t\t   MAC2STR(data.driver_gtk_rekey.bssid));\n\tdata.driver_gtk_rekey.replay_ctr =\n\t\tnla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);\n\twpa_hexdump(MSG_DEBUG, \"capwap: Rekey offload - Replay Counter\",\n\t\t    data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);\n\twpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);\n}\n\n\nstatic void capwap_pmksa_candidate_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t  struct nlattr **tb)\n{\n\tstruct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];\n\tstatic struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {\n\t\t[NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },\n\t\t[NL80211_PMKSA_CANDIDATE_BSSID] = {\n\t\t\t.minlen = ETH_ALEN,\n\t\t\t.maxlen = ETH_ALEN,\n\t\t},\n\t\t[NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },\n\t};\n\tunion wpa_event_data data;\n\n\tif (!tb[NL80211_ATTR_PMKSA_CANDIDATE])\n\t\treturn;\n\tif (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,\n\t\t\t     tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))\n\t\treturn;\n\tif (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||\n\t    !cand[NL80211_PMKSA_CANDIDATE_BSSID])\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tos_memcpy(data.pmkid_candidate.bssid,\n\t\t  nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);\n\tdata.pmkid_candidate.index =\n\t\tnla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);\n\tdata.pmkid_candidate.preauth =\n\t\tcand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;\n\twpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);\n}\n\n\nstatic int process_event(struct nl_msg *msg, void *arg)\n{\n\n\tstruct wpa_driver_capwap_data *drv = arg;\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (tb[NL80211_ATTR_IFINDEX]) {\n\t\tint ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);\n\t\tif (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignored event (cmd=%d)\"\n\t\t\t\t   \" for foreign interface (ifindex %d)\",\n\t\t\t\t   gnlh->cmd, ifindex);\n\t\t\treturn NL_SKIP;\n\t\t}\n\t}\n\n\tif (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&\n\t    (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS ||\n\t     gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) {\n\t\twpa_driver_capwap_set_mode(&drv->first_bss,\n\t\t\t\t\t    drv->ap_scan_as_station);\n\t\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n\t}\n\n\tswitch (gnlh->cmd) {\n\tcase NL80211_CMD_TRIGGER_SCAN:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Scan trigger\");\n\t\tbreak;\n\tcase NL80211_CMD_START_SCHED_SCAN:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan started\");\n\t\tbreak;\n\tcase NL80211_CMD_SCHED_SCAN_STOPPED:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stopped\");\n\t\twpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);\n\t\tbreak;\n\tcase NL80211_CMD_NEW_SCAN_RESULTS:\n\t\twpa_printf(MSG_DEBUG, \"capwap: New scan results available\");\n\t\tdrv->scan_complete_events = 1;\n\t\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv,\n\t\t\t\t     drv->ctx);\n\t\tsend_scan_event(drv, 0, tb);\n\t\tbreak;\n\tcase NL80211_CMD_SCHED_SCAN_RESULTS:\n\t\twpa_printf(MSG_DEBUG,\n\t\t\t   \"capwap: New sched scan results available\");\n\t\tsend_scan_event(drv, 0, tb);\n\t\tbreak;\n\tcase NL80211_CMD_SCAN_ABORTED:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Scan aborted\");\n\t\t/*\n\t\t * Need to indicate that scan results are available in order\n\t\t * not to make wpa_supplicant stop its scanning.\n\t\t */\n\t\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv,\n\t\t\t\t     drv->ctx);\n\t\tsend_scan_event(drv, 1, tb);\n\t\tbreak;\n\tcase NL80211_CMD_AUTHENTICATE:\n\tcase NL80211_CMD_ASSOCIATE:\n\tcase NL80211_CMD_DEAUTHENTICATE:\n\tcase NL80211_CMD_DISASSOCIATE:\n\tcase NL80211_CMD_FRAME:\n\tcase NL80211_CMD_FRAME_TX_STATUS:\n\tcase NL80211_CMD_UNPROT_DEAUTHENTICATE:\n\tcase NL80211_CMD_UNPROT_DISASSOCIATE:\n\t\tmlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],\n\t\t\t   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],\n\t\t\t   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],\n\t\t\t   tb[NL80211_ATTR_COOKIE]);\n\t\tbreak;\n\tcase NL80211_CMD_CONNECT:\n\tcase NL80211_CMD_ROAM:\n\t\tmlme_event_connect(drv, gnlh->cmd,\n\t\t\t\t   tb[NL80211_ATTR_STATUS_CODE],\n\t\t\t\t   tb[NL80211_ATTR_MAC],\n\t\t\t\t   tb[NL80211_ATTR_REQ_IE],\n\t\t\t\t   tb[NL80211_ATTR_RESP_IE]);\n\t\tbreak;\n\tcase NL80211_CMD_DISCONNECT:\n\t\tmlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],\n\t\t\t\t      tb[NL80211_ATTR_MAC]);\n\t\tbreak;\n\tcase NL80211_CMD_MICHAEL_MIC_FAILURE:\n\t\tmlme_event_michael_mic_failure(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_JOIN_IBSS:\n\t\tmlme_event_join_ibss(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_REMAIN_ON_CHANNEL:\n\t\tmlme_event_remain_on_channel(drv, 0, tb);\n\t\tbreak;\n\tcase NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:\n\t\tmlme_event_remain_on_channel(drv, 1, tb);\n\t\tbreak;\n\tcase NL80211_CMD_NOTIFY_CQM:\n\t\tcapwap_cqm_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_REG_CHANGE:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Regulatory domain change\");\n\t\twpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,\n\t\t\t\t     NULL);\n\t\tbreak;\n\tcase NL80211_CMD_REG_BEACON_HINT:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Regulatory beacon hint\");\n\t\twpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,\n\t\t\t\t     NULL);\n\t\tbreak;\n\tcase NL80211_CMD_NEW_STATION:\n\t\tcapwap_new_station_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_DEL_STATION:\n\t\tcapwap_del_station_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_SET_REKEY_OFFLOAD:\n\t\tcapwap_rekey_offload_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_PMKSA_CANDIDATE:\n\t\tcapwap_pmksa_candidate_event(drv, tb);\n\t\tbreak;\n\tdefault:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignored unknown event \"\n\t\t\t   \"(cmd=%d)\", gnlh->cmd);\n\t\tbreak;\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic void wpa_driver_capwap_event_receive(int sock, void *eloop_ctx,\n\t\t\t\t\t     void *handle)\n{\n\n\tstruct nl_cb *cb;\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Event message available\");\n\n\tcb = nl_cb_clone(drv->global->nl_cb);\n\tif (!cb)\n\t\treturn;\n\tnl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);\n\tnl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv);\n\tnl_recvmsgs(handle, cb);\n\tnl_cb_put(cb);\n}\n\n\n/**\n * wpa_driver_capwap_set_country - ask capwap to set the regulatory domain\n * @priv: driver_capwap private data\n * @alpha2_arg: country to which to switch to\n * Returns: 0 on success, -1 on failure\n *\n * This asks capwap to set the regulatory domain for given\n * country ISO / IEC alpha2.\n */\nstatic int wpa_driver_capwap_set_country(void *priv, const char *alpha2_arg)\n{\n\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tchar alpha2[3];\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\talpha2[0] = alpha2_arg[0];\n\talpha2[1] = alpha2_arg[1];\n\talpha2[2] = '\\0';\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);\n\n\tNLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL))\n\t\treturn -EINVAL;\n\treturn 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -EINVAL;\n}\n\n\nstruct wiphy_info_data {\n\tstruct wpa_driver_capa *capa;\n\n\tunsigned int error:1;\n};\n\n\nstatic int wiphy_info_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct wiphy_info_data *info = arg;\n\tint p2p_go_supported = 0, p2p_client_supported = 0;\n\tint p2p_concurrent = 0;\n\tint auth_supported = 0, connect_supported = 0;\n\tstruct wpa_driver_capa *capa = info->capa;\n\tstatic struct nla_policy\n\tiface_combination_policy[NUM_NL80211_IFACE_COMB] = {\n\t\t[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },\n\t\t[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },\n\t\t[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },\n\t\t[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },\n\t},\n\tiface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {\n\t\t[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },\n\t\t[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },\n\t};\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])\n\t\tcapa->max_scan_ssids =\n\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);\n\n\tif (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])\n\t\tcapa->max_sched_scan_ssids =\n\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);\n\n\tif (tb[NL80211_ATTR_MAX_MATCH_SETS])\n\t\tcapa->max_match_sets =\n\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);\n\n\tif (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {\n\t\tstruct nlattr *nl_mode;\n\t\tint i;\n\t\tnla_for_each_nested(nl_mode,\n\t\t\t\t    tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {\n\t\t\tswitch (nla_type(nl_mode)) {\n\t\t\tcase NL80211_IFTYPE_AP:\n\t\t\t\tcapa->flags |= WPA_DRIVER_FLAGS_AP;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_IFTYPE_P2P_GO:\n\t\t\t\tp2p_go_supported = 1;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_IFTYPE_P2P_CLIENT:\n\t\t\t\tp2p_client_supported = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tb[NL80211_ATTR_INTERFACE_COMBINATIONS]) {\n\t\tstruct nlattr *nl_combi;\n\t\tint rem_combi;\n\n\t\tnla_for_each_nested(nl_combi,\n\t\t\t\t    tb[NL80211_ATTR_INTERFACE_COMBINATIONS],\n\t\t\t\t    rem_combi) {\n\t\t\tstruct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];\n\t\t\tstruct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];\n\t\t\tstruct nlattr *nl_limit, *nl_mode;\n\t\t\tint err, rem_limit, rem_mode;\n\t\t\tint combination_has_p2p = 0, combination_has_mgd = 0;\n\n\t\t\terr = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,\n\t\t\t\t\t       nl_combi,\n\t\t\t\t\t       iface_combination_policy);\n\t\t\tif (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||\n\t\t\t    !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||\n\t\t\t    !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])\n\t\t\t\tgoto broken_combination;\n\n\t\t\tnla_for_each_nested(nl_limit,\n\t\t\t\t\t    tb_comb[NL80211_IFACE_COMB_LIMITS],\n\t\t\t\t\t    rem_limit) {\n\t\t\t\terr = nla_parse_nested(tb_limit,\n\t\t\t\t\t\t       MAX_NL80211_IFACE_LIMIT,\n\t\t\t\t\t\t       nl_limit,\n\t\t\t\t\t\t       iface_limit_policy);\n\t\t\t\tif (err ||\n\t\t\t\t    !tb_limit[NL80211_IFACE_LIMIT_TYPES])\n\t\t\t\t\tgoto broken_combination;\n\n\t\t\t\tnla_for_each_nested(\n\t\t\t\t\tnl_mode,\n\t\t\t\t\ttb_limit[NL80211_IFACE_LIMIT_TYPES],\n\t\t\t\t\trem_mode) {\n\t\t\t\t\tint ift = nla_type(nl_mode);\n\t\t\t\t\tif (ift == NL80211_IFTYPE_P2P_GO ||\n\t\t\t\t\t    ift == NL80211_IFTYPE_P2P_CLIENT)\n\t\t\t\t\t\tcombination_has_p2p = 1;\n\t\t\t\t\tif (ift == NL80211_IFTYPE_STATION)\n\t\t\t\t\t\tcombination_has_mgd = 1;\n\t\t\t\t}\n\t\t\t\tif (combination_has_p2p && combination_has_mgd)\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (combination_has_p2p && combination_has_mgd) {\n\t\t\t\tp2p_concurrent = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\nbroken_combination:\n\t\t\t;\n\t\t}\n\t}\n\n\tif (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {\n\t\tstruct nlattr *nl_cmd;\n\t\tint i;\n\n\t\tnla_for_each_nested(nl_cmd,\n\t\t\t\t    tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) {\n\t\t\tswitch (nla_get_u32(nl_cmd)) {\n\t\t\tcase NL80211_CMD_AUTHENTICATE:\n\t\t\t\tauth_supported = 1;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_CMD_CONNECT:\n\t\t\t\tconnect_supported = 1;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_CMD_START_SCHED_SCAN:\n\t\t\t\t/*\n\t\t\t\t * Disabled for 1.x for now as it is\n\t\t\t\t * broken there due to the way it ends\n\t\t\t\t * up getting used.\n\t\t\t\tcapa->sched_scan_supported = 1;\n\t\t\t\t */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Using driver-based \"\n\t\t\t   \"off-channel TX\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;\n\t}\n\n\tif (tb[NL80211_ATTR_ROAM_SUPPORT]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Using driver-based roaming\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;\n\t}\n\n\t/* default to 5000 since early versions of mac80211 don't set it */\n\tcapa->max_remain_on_chan = 5000;\n\n\tif (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION])\n\t\tcapa->max_remain_on_chan =\n\t\t\tnla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);\n\n\tif (auth_supported)\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_SME;\n\telse if (!connect_supported) {\n\t\twpa_printf(MSG_INFO, \"capwap: Driver does not support \"\n\t\t\t   \"authentication/association or connect commands\");\n\t\tinfo->error = 1;\n\t}\n\n\tif (p2p_go_supported && p2p_client_supported)\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;\n\tif (p2p_concurrent) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Use separate P2P group \"\n\t\t\t   \"interface (driver advertised support)\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;\n\t}\n\n\tif (tb[NL80211_ATTR_TDLS_SUPPORT]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS supported\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;\n\n\t\tif (tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS external setup\");\n\t\t\tcapa->flags |=\n\t\t\t\tWPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;\n\t\t}\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int wpa_driver_capwap_get_info(struct wpa_driver_capwap_data *drv,\n\t\t\t\t       struct wiphy_info_data *info)\n{\n\treturn 0;\n\n}\n\n\nstatic int wpa_driver_capwap_capa(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t\t\t4.wpa_driver_capwap_capa\");\n\tstruct wiphy_info_data info;\n\n\tif (wpa_driver_capwap_get_info(drv, &info))\n\t\treturn -1;\n\n\n\n\tdrv->has_capability = 1;\n\t/* For now, assume TKIP, CCMP, WPA, WPA2 are supported */\n\tdrv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |\n\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |\n\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA2 |\n\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;\n\tdrv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |\n\t\tWPA_DRIVER_CAPA_ENC_WEP104 |\n\t\tWPA_DRIVER_CAPA_ENC_TKIP |\n\t\tWPA_DRIVER_CAPA_ENC_CCMP;\n\tdrv->capa.auth = WPA_DRIVER_AUTH_OPEN |\n\t\tWPA_DRIVER_AUTH_SHARED |\n\t\tWPA_DRIVER_AUTH_LEAP;\n\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;\n\n\treturn 0;\n}\n\n\n#ifdef ANDROID\nstatic int android_genl_ctrl_resolve(struct nl_handle *handle,\n\t\t\t\t     const char *name)\n{\n\t/*\n\t * Android ICS has very minimal genl_ctrl_resolve() implementation, so\n\t * need to work around that.\n\t */\n\tstruct nl_cache *cache = NULL;\n\tstruct genl_family *capwap = NULL;\n\tint id = -1;\n\n\tif (genl_ctrl_alloc_cache(handle, &cache) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate generic \"\n\t\t\t   \"netlink cache\");\n\t\tgoto fail;\n\t}\n\n\tcapwap = genl_ctrl_search_by_name(cache, name);\n\tif (capwap == NULL)\n\t\tgoto fail;\n\n\tid = genl_family_get_id(capwap);\n\nfail:\n\tif (capwap)\n\t\tgenl_family_put(capwap);\n\tif (cache)\n\t\tnl_cache_free(cache);\n\n\treturn id;\n}\n#define genl_ctrl_resolve android_genl_ctrl_resolve\n#endif /* ANDROID */\n\n\nstatic int wpa_driver_capwap_init_nl_global(struct capwap_global *global)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t2.wpa_driver_capwap_init_nl_global\");\n\tglobal->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);\n\tif (global->nl_cb == NULL) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate netlink \"\n\t\t\t   \"callbacks\");\n\t\treturn -1;\n\t}\n\n\tif (nl_create_handles(&global->nl, global->nl_cb, \"nl\"))\n\t\treturn -1;\n\n\tglobal->capwap = genl_ctrl_search_by_name(global->nl.cache,\n\t\t\t\t\t\t   \"nl80211\");\n\tif (global->capwap == NULL) {\n\t\twpa_printf(MSG_ERROR, \"capwap: 'capwap' generic netlink not \"\n\t\t\t   \"found\");\n\t}\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_init_nl(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t\t1.wpa_driver_capwap_init_nl\");\n\treturn 0;\n}\n\n\nstatic void wpa_driver_capwap_rfkill_blocked(void *ctx)\n{\n\twpa_printf(MSG_DEBUG, \"capwap: RFKILL blocked\");\n\t/*\n\t * This may be for any interface; use ifdown event to disable\n\t * interface.\n\t */\n}\n\n\nstatic void wpa_driver_capwap_rfkill_unblocked(void *ctx)\n{\n\tstruct wpa_driver_capwap_data *drv = ctx;\n\twpa_printf(MSG_DEBUG, \"capwap: RFKILL unblocked\");\n\tif (linux_set_iface_flags(drv->global->ioctl_sock,\n\t\t\t\t  drv->first_bss.ifname, 1)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Could not set interface UP \"\n\t\t\t   \"after rfkill unblock\");\n\t\treturn;\n\t}\n\t/* rtnetlink ifup handler will report interface as enabled */\n}\n\n\nstatic void capwap_get_phy_name(struct wpa_driver_capwap_data *drv)\n{\n\n\tdrv->phyname[0] = '\\0';\n\treturn;\n\n\n}\n\n\n#ifdef CONFIG_AP\nstatic void capwap_l2_read(void *ctx, const u8 *src_addr, const u8 *buf,\n\t\t\t    size_t len)\n{\n\twpa_printf(MSG_DEBUG, \"capwap: l2_packet read %u\",\n\t\t   (unsigned int) len);\n}\n#endif /* CONFIG_AP */\n\n\n/**\n * wpa_driver_capwap_init - Initialize capwap driver interface\n * @ctx: context to be used when calling wpa_supplicant functions,\n * e.g., wpa_supplicant_event()\n * @ifname: interface name, e.g., wlan0\n * @global_priv: private driver global data from global_init()\n * Returns: Pointer to private data, %NULL on failure\n */\nstatic void * wpa_driver_capwap_init(void *ctx, const char *ifname,\n\t\t\t\t      void *global_priv)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t1.wpa_driver_capwap_init\");\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct rfkill_config *rcfg;\n\tstruct i802_bss *bss;\n\n\tif (global_priv == NULL)\n\t\treturn NULL;\n\tdrv = os_zalloc(sizeof(*drv));\n\tif (drv == NULL)\n\t\treturn NULL;\n\tdrv->global = global_priv;\n\tdrv->ctx = ctx;\n\tbss = &drv->first_bss;\n\tbss->drv = drv;\n\tos_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));\n\tdrv->monitor_ifidx = -1;\n\tdrv->monitor_sock = -1;\n\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n\n\tif (wpa_driver_capwap_init_nl(drv)) {\n\t\tos_free(drv);\n\t\treturn NULL;\n\t}\n\n\tcapwap_get_phy_name(drv);\n\n\trcfg = os_zalloc(sizeof(*rcfg));\n\tif (rcfg == NULL)\n\t\tgoto failed;\n\trcfg->ctx = drv;\n\tos_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));\n\trcfg->blocked_cb = wpa_driver_capwap_rfkill_blocked;\n\trcfg->unblocked_cb = wpa_driver_capwap_rfkill_unblocked;\n\tdrv->rfkill = rfkill_init(rcfg);\n\tif (drv->rfkill == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: RFKILL status not available\");\n\t\tos_free(rcfg);\n\t}\n\n\tif (wpa_driver_capwap_finish_drv_init(drv))\n\t\tgoto failed;\n\n#ifdef CONFIG_AP\n\tdrv->l2 = l2_packet_init(ifname, NULL, ETH_P_EAPOL,\n\t\t\t\t capwap_l2_read, drv, 0);\n#endif /* CONFIG_AP */\n\n\tif (drv->global) {\n\t\tdl_list_add(&drv->global->interfaces, &drv->list);\n\t\tdrv->in_interface_list = 1;\n\t}\n\n\treturn bss;\n\nfailed:\n\twpa_driver_capwap_deinit(bss);\n\treturn NULL;\n}\n\n\nstatic int capwap_register_frame(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct nl_handle *nl_handle,\n\t\t\t\t  u16 type, const u8 *match, size_t match_len)\n{\n\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);\n\tNLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);\n\n\tret = send_and_recv(drv, nl_handle, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Register frame command \"\n\t\t\t   \"failed (type=%u): ret=%d (%s)\",\n\t\t\t   type, ret, strerror(-ret));\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: Register frame match\",\n\t\t\t    match, match_len);\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int capwap_register_action_frame(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t const u8 *match, size_t match_len)\n{\n\tu16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);\n\treturn capwap_register_frame(drv, drv->nl_event.handle,\n\t\t\t\t      type, match, match_len);\n}\n\n\nstatic int capwap_register_action_frames(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t\t\t6.capwap_register_action_frames\");\n\treturn 0;\n\n}\n\n\nstatic void wpa_driver_capwap_send_rfkill(void *eloop_ctx, void *timeout_ctx)\n{\n\twpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);\n}\n\n\nstatic int\nwpa_driver_capwap_finish_drv_init(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t\t3.wpa_driver_capwap_finish_drv_init\");\n\n\tstruct i802_bss *bss = &drv->first_bss;\n\tint send_rfkill_event = 0;\n\n\tdrv->ifindex = if_nametoindex(bss->ifname);\n\tdrv->first_bss.ifindex = drv->ifindex;\n\n#ifndef HOSTAPD\n\n\t/*\n\t * Make sure the interface starts up in station mode unless this is a\n\t * dynamically added interface (e.g., P2P) that was already configured\n\t * with proper iftype.\n\t */\n\n\tif (drv->ifindex != drv->global->if_add_ifindex &&\n\t    wpa_driver_capwap_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Could not configure driver to \"\n\t\t\t   \"use managed mode\");\n\t\treturn -1;\n\t}\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {\n\t\tif (rfkill_is_blocked(drv->rfkill)) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Could not yet enable \"\n\t\t\t\t   \"interface '%s' due to rfkill\",\n\t\t\t\t   bss->ifname);\n\t\t\tdrv->if_disabled = 1;\n\t\t\tsend_rfkill_event = 1;\n\t\t} else {\n\t\t\twpa_printf(MSG_ERROR, \"capwap: Could not set \"\n\t\t\t\t   \"interface '%s' UP\", bss->ifname);\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,\n\t\t\t       1, IF_OPER_DORMANT);\n\n#endif /* HOSTAPD */\n\n\tif (wpa_driver_capwap_capa(drv))\n\t\treturn -1;\n\n\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t       drv->addr))\n\t\treturn -1;\n\n\n\n\n\n\n\tif (capwap_register_action_frames(drv) < 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to register Action \"\n\t\t\t   \"frame processing - ignore for now\");\n\t\t/*\n\t\t * Older kernel versions did not support this, so ignore the\n\t\t * error for now. Some functionality may not be available\n\t\t * because of this.\n\t\t */\n\t}\n\n\tif (send_rfkill_event) {\n\t\teloop_register_timeout(0, 0, wpa_driver_capwap_send_rfkill,\n\t\t\t\t       drv, drv->ctx);\n\t}\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_del_beacon(struct wpa_driver_capwap_data *drv)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\n/**\n * wpa_driver_capwap_deinit - Deinitialize capwap driver interface\n * @priv: Pointer to private capwap data from wpa_driver_capwap_init()\n *\n * Shut down driver interface and processing of driver events. Free\n * private data buffer if one was allocated in wpa_driver_capwap_init().\n */\nstatic void wpa_driver_capwap_deinit(void *priv)\n{\n\n\twpa_printf(MSG_DEBUG,\"wpa_driver_capwap_deinit\\n\");\n/*\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tfake_mgmt_null_rates(drv->ctx);\n*/\n}\n\n\n/**\n * wpa_driver_capwap_scan_timeout - Scan timeout to report scan completion\n * @eloop_ctx: Driver private data\n * @timeout_ctx: ctx argument given to wpa_driver_capwap_init()\n *\n * This function can be used as registered timeout when starting a scan to\n * generate a scan completed event if the driver does not report this.\n */\nstatic void wpa_driver_capwap_scan_timeout(void *eloop_ctx, void *timeout_ctx)\n{\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\tif (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {\n\t\twpa_driver_capwap_set_mode(&drv->first_bss,\n\t\t\t\t\t    drv->ap_scan_as_station);\n\t\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n\t}\n\twpa_printf(MSG_DEBUG, \"Scan timeout - try to get results\");\n\twpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);\n}\n\n\n/**\n * wpa_driver_capwap_scan - Request the driver to initiate scan\n * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n * @params: Scan parameters\n * Returns: 0 on success, -1 on failure\n */\nstatic int wpa_driver_capwap_scan(void *priv,\n\t\t\t\t   struct wpa_driver_scan_params *params)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = 0, timeout;\n\tstruct nl_msg *msg, *ssids, *freqs, *rates;\n\tsize_t i;\n\n\tmsg = nlmsg_alloc();\n\tssids = nlmsg_alloc();\n\tfreqs = nlmsg_alloc();\n\trates = nlmsg_alloc();\n\tif (!msg || !ssids || !freqs || !rates) {\n\t\tnlmsg_free(msg);\n\t\tnlmsg_free(ssids);\n\t\tnlmsg_free(freqs);\n\t\tnlmsg_free(rates);\n\t\treturn -1;\n\t}\n\n\tos_free(drv->filter_ssids);\n\tdrv->filter_ssids = params->filter_ssids;\n\tparams->filter_ssids = NULL;\n\tdrv->num_filter_ssids = params->num_filter_ssids;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TRIGGER_SCAN);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tfor (i = 0; i < params->num_ssids; i++) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Scan SSID\",\n\t\t\t\t  params->ssids[i].ssid,\n\t\t\t\t  params->ssids[i].ssid_len);\n\t\tNLA_PUT(ssids, i + 1, params->ssids[i].ssid_len,\n\t\t\tparams->ssids[i].ssid);\n\t}\n\tif (params->num_ssids)\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);\n\n\tif (params->extra_ies) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Scan extra IEs\",\n\t\t\t\t  params->extra_ies, params->extra_ies_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,\n\t\t\tparams->extra_ies);\n\t}\n\n\tif (params->freqs) {\n\t\tfor (i = 0; params->freqs[i]; i++) {\n\t\t\twpa_printf(MSG_MSGDUMP, \"capwap: Scan frequency %u \"\n\t\t\t\t   \"MHz\", params->freqs[i]);\n\t\t\tNLA_PUT_U32(freqs, i + 1, params->freqs[i]);\n\t\t}\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);\n\t}\n\n\tif (params->p2p_probe) {\n\t\t/*\n\t\t * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates\n\t\t * by masking out everything else apart from the OFDM rates 6,\n\t\t * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz\n\t\t * rates are left enabled.\n\t\t */\n\t\tNLA_PUT(rates, NL80211_BAND_2GHZ, 8,\n\t\t\t\"\\x0c\\x12\\x18\\x24\\x30\\x48\\x60\\x6c\");\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates);\n\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Scan trigger failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n#ifdef HOSTAPD\n\t\tif (is_ap_interface(drv->nlmode)) {\n\t\t\t/*\n\t\t\t * mac80211 does not allow scan requests in AP mode, so\n\t\t\t * try to do this in station mode.\n\t\t\t */\n\t\t\tif (wpa_driver_capwap_set_mode(\n\t\t\t\t    bss, NL80211_IFTYPE_STATION))\n\t\t\t\tgoto nla_put_failure;\n\n\t\t\tif (wpa_driver_capwap_scan(drv, params)) {\n\t\t\t\twpa_driver_capwap_set_mode(bss, drv->nlmode);\n\t\t\t\tgoto nla_put_failure;\n\t\t\t}\n\n\t\t\t/* Restore AP mode when processing scan results */\n\t\t\tdrv->ap_scan_as_station = drv->nlmode;\n\t\t\tret = 0;\n\t\t} else\n\t\t\tgoto nla_put_failure;\n#else /* HOSTAPD */\n\t\tgoto nla_put_failure;\n#endif /* HOSTAPD */\n\t}\n\n\t/* Not all drivers generate \"scan completed\" wireless event, so try to\n\t * read results after a timeout. */\n\ttimeout = 10;\n\tif (drv->scan_complete_events) {\n\t\t/*\n\t\t * The driver seems to deliver events to notify when scan is\n\t\t * complete, so use longer timeout to avoid race conditions\n\t\t * with scanning and following association request.\n\t\t */\n\t\ttimeout = 30;\n\t}\n\twpa_printf(MSG_DEBUG, \"Scan requested (ret=%d) - scan timeout %d \"\n\t\t   \"seconds\", ret, timeout);\n\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv, drv->ctx);\n\teloop_register_timeout(timeout, 0, wpa_driver_capwap_scan_timeout,\n\t\t\t       drv, drv->ctx);\n\nnla_put_failure:\n\tnlmsg_free(ssids);\n\tnlmsg_free(msg);\n\tnlmsg_free(freqs);\n\tnlmsg_free(rates);\n\treturn ret;\n}\n\n\n/**\n * wpa_driver_capwap_sched_scan - Initiate a scheduled scan\n * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n * @params: Scan parameters\n * @interval: Interval between scan cycles in milliseconds\n * Returns: 0 on success, -1 on failure or if not supported\n */\nstatic int wpa_driver_capwap_sched_scan(void *priv,\n\t\t\t\t\t struct wpa_driver_scan_params *params,\n\t\t\t\t\t u32 interval)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = 0;\n\tstruct nl_msg *msg, *ssids, *freqs, *match_set_ssid, *match_sets;\n\tsize_t i;\n\n\tmsg = nlmsg_alloc();\n\tssids = nlmsg_alloc();\n\tfreqs = nlmsg_alloc();\n\tif (!msg || !ssids || !freqs) {\n\t\tnlmsg_free(msg);\n\t\tnlmsg_free(ssids);\n\t\tnlmsg_free(freqs);\n\t\treturn -1;\n\t}\n\n\tos_free(drv->filter_ssids);\n\tdrv->filter_ssids = params->filter_ssids;\n\tparams->filter_ssids = NULL;\n\tdrv->num_filter_ssids = params->num_filter_ssids;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_START_SCHED_SCAN);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);\n\n\tif (drv->num_filter_ssids) {\n\t\tmatch_sets = nlmsg_alloc();\n\n\t\tfor (i = 0; i < drv->num_filter_ssids; i++) {\n\t\t\twpa_hexdump_ascii(MSG_MSGDUMP,\n\t\t\t\t\t  \"capwap: Sched scan filter SSID\",\n\t\t\t\t\t  drv->filter_ssids[i].ssid,\n\t\t\t\t\t  drv->filter_ssids[i].ssid_len);\n\n\t\t\tmatch_set_ssid = nlmsg_alloc();\n\t\t\tnla_put(match_set_ssid,\n\t\t\t\tNL80211_ATTR_SCHED_SCAN_MATCH_SSID,\n\t\t\t\tdrv->filter_ssids[i].ssid_len,\n\t\t\t\tdrv->filter_ssids[i].ssid);\n\n\t\t\tnla_put_nested(match_sets, i + 1, match_set_ssid);\n\n\t\t\tnlmsg_free(match_set_ssid);\n\t\t}\n\n\t\tnla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,\n\t\t\t       match_sets);\n\t\tnlmsg_free(match_sets);\n\t}\n\n\tfor (i = 0; i < params->num_ssids; i++) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Sched scan SSID\",\n\t\t\t\t  params->ssids[i].ssid,\n\t\t\t\t  params->ssids[i].ssid_len);\n\t\tNLA_PUT(ssids, i + 1, params->ssids[i].ssid_len,\n\t\t\tparams->ssids[i].ssid);\n\t}\n\tif (params->num_ssids)\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);\n\n\tif (params->extra_ies) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Sched scan extra IEs\",\n\t\t\t\t  params->extra_ies, params->extra_ies_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,\n\t\t\tparams->extra_ies);\n\t}\n\n\tif (params->freqs) {\n\t\tfor (i = 0; params->freqs[i]; i++) {\n\t\t\twpa_printf(MSG_MSGDUMP, \"capwap: Scan frequency %u \"\n\t\t\t\t   \"MHz\", params->freqs[i]);\n\t\t\tNLA_PUT_U32(freqs, i + 1, params->freqs[i]);\n\t\t}\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\n\t/* TODO: if we get an error here, we should fall back to normal scan */\n\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan start failed: \"\n\t\t\t   \"ret=%d (%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Sched scan requested (ret=%d) - \"\n\t\t   \"scan interval %d msec\", ret, interval);\n\nnla_put_failure:\n\tnlmsg_free(ssids);\n\tnlmsg_free(msg);\n\tnlmsg_free(freqs);\n\treturn ret;\n}\n\n\n/**\n * wpa_driver_capwap_stop_sched_scan - Stop a scheduled scan\n * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n * Returns: 0 on success, -1 on failure or if not supported\n */\nstatic int wpa_driver_capwap_stop_sched_scan(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = 0;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stop failed: \"\n\t\t\t   \"ret=%d (%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stop sent (ret=%d)\", ret);\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic const u8 * capwap_get_ie(const u8 *ies, size_t ies_len, u8 ie)\n{\n\tconst u8 *end, *pos;\n\n\tif (ies == NULL)\n\t\treturn NULL;\n\n\tpos = ies;\n\tend = ies + ies_len;\n\n\twhile (pos + 1 < end) {\n\t\tif (pos + 2 + pos[1] > end)\n\t\t\tbreak;\n\t\tif (pos[0] == ie)\n\t\t\treturn pos;\n\t\tpos += 2 + pos[1];\n\t}\n\n\treturn NULL;\n}\n\n\nstatic int capwap_scan_filtered(struct wpa_driver_capwap_data *drv,\n\t\t\t\t const u8 *ie, size_t ie_len)\n{\n\tconst u8 *ssid;\n\tsize_t i;\n\n\tif (drv->filter_ssids == NULL)\n\t\treturn 0;\n\n\tssid = capwap_get_ie(ie, ie_len, WLAN_EID_SSID);\n\tif (ssid == NULL)\n\t\treturn 1;\n\n\tfor (i = 0; i < drv->num_filter_ssids; i++) {\n\t\tif (ssid[1] == drv->filter_ssids[i].ssid_len &&\n\t\t    os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==\n\t\t    0)\n\t\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n\n\nstatic int bss_info_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *bss[NL80211_BSS_MAX + 1];\n\tstatic struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {\n\t\t[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },\n\t\t[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_TSF] = { .type = NLA_U64 },\n\t\t[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },\n\t\t[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },\n\t\t[NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },\n\t\t[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },\n\t\t[NL80211_BSS_STATUS] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },\n\t};\n\tstruct capwap_bss_info_arg *_arg = arg;\n\tstruct wpa_scan_results *res = _arg->res;\n\tstruct wpa_scan_res **tmp;\n\tstruct wpa_scan_res *r;\n\tconst u8 *ie, *beacon_ie;\n\tsize_t ie_len, beacon_ie_len;\n\tu8 *pos;\n\tsize_t i;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb[NL80211_ATTR_BSS])\n\t\treturn NL_SKIP;\n\tif (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],\n\t\t\t     bss_policy))\n\t\treturn NL_SKIP;\n\tif (bss[NL80211_BSS_STATUS]) {\n\t\tenum nl80211_bss_status status;\n\t\tstatus = nla_get_u32(bss[NL80211_BSS_STATUS]);\n\t\tif (status == NL80211_BSS_STATUS_ASSOCIATED &&\n\t\t    bss[NL80211_BSS_FREQUENCY]) {\n\t\t\t_arg->assoc_freq =\n\t\t\t\tnla_get_u32(bss[NL80211_BSS_FREQUENCY]);\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Associated on %u MHz\",\n\t\t\t\t   _arg->assoc_freq);\n\t\t}\n\t\tif (status == NL80211_BSS_STATUS_ASSOCIATED &&\n\t\t    bss[NL80211_BSS_BSSID]) {\n\t\t\tos_memcpy(_arg->assoc_bssid,\n\t\t\t\t  nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Associated with \"\n\t\t\t\t   MACSTR, MAC2STR(_arg->assoc_bssid));\n\t\t}\n\t}\n\tif (!res)\n\t\treturn NL_SKIP;\n\tif (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {\n\t\tie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);\n\t\tie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);\n\t} else {\n\t\tie = NULL;\n\t\tie_len = 0;\n\t}\n\tif (bss[NL80211_BSS_BEACON_IES]) {\n\t\tbeacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);\n\t\tbeacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);\n\t} else {\n\t\tbeacon_ie = NULL;\n\t\tbeacon_ie_len = 0;\n\t}\n\n\tif (capwap_scan_filtered(_arg->drv, ie ? ie : beacon_ie,\n\t\t\t\t  ie ? ie_len : beacon_ie_len))\n\t\treturn NL_SKIP;\n\n\tr = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);\n\tif (r == NULL)\n\t\treturn NL_SKIP;\n\tif (bss[NL80211_BSS_BSSID])\n\t\tos_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),\n\t\t\t  ETH_ALEN);\n\tif (bss[NL80211_BSS_FREQUENCY])\n\t\tr->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);\n\tif (bss[NL80211_BSS_BEACON_INTERVAL])\n\t\tr->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);\n\tif (bss[NL80211_BSS_CAPABILITY])\n\t\tr->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);\n\tr->flags |= WPA_SCAN_NOISE_INVALID;\n\tif (bss[NL80211_BSS_SIGNAL_MBM]) {\n\t\tr->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);\n\t\tr->level /= 100; /* mBm to dBm */\n\t\tr->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;\n\t} else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {\n\t\tr->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);\n\t\tr->flags |= WPA_SCAN_QUAL_INVALID;\n\t} else\n\t\tr->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;\n\tif (bss[NL80211_BSS_TSF])\n\t\tr->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);\n\tif (bss[NL80211_BSS_SEEN_MS_AGO])\n\t\tr->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);\n\tr->ie_len = ie_len;\n\tpos = (u8 *) (r + 1);\n\tif (ie) {\n\t\tos_memcpy(pos, ie, ie_len);\n\t\tpos += ie_len;\n\t}\n\tr->beacon_ie_len = beacon_ie_len;\n\tif (beacon_ie)\n\t\tos_memcpy(pos, beacon_ie, beacon_ie_len);\n\n\tif (bss[NL80211_BSS_STATUS]) {\n\t\tenum nl80211_bss_status status;\n\t\tstatus = nla_get_u32(bss[NL80211_BSS_STATUS]);\n\t\tswitch (status) {\n\t\tcase NL80211_BSS_STATUS_AUTHENTICATED:\n\t\t\tr->flags |= WPA_SCAN_AUTHENTICATED;\n\t\t\tbreak;\n\t\tcase NL80211_BSS_STATUS_ASSOCIATED:\n\t\t\tr->flags |= WPA_SCAN_ASSOCIATED;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t * cfg80211 maintains separate BSS table entries for APs if the same\n\t * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does\n\t * not use frequency as a separate key in the BSS table, so filter out\n\t * duplicated entries. Prefer associated BSS entry in such a case in\n\t * order to get the correct frequency into the BSS table.\n\t */\n\tfor (i = 0; i < res->num; i++) {\n\t\tconst u8 *s1, *s2;\n\t\tif (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)\n\t\t\tcontinue;\n\n\t\ts1 = capwap_get_ie((u8 *) (res->res[i] + 1),\n\t\t\t\t    res->res[i]->ie_len, WLAN_EID_SSID);\n\t\ts2 = capwap_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);\n\t\tif (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||\n\t\t    os_memcmp(s1, s2, 2 + s1[1]) != 0)\n\t\t\tcontinue;\n\n\t\t/* Same BSSID,SSID was already included in scan results */\n\t\twpa_printf(MSG_DEBUG, \"capwap: Remove duplicated scan result \"\n\t\t\t   \"for \" MACSTR, MAC2STR(r->bssid));\n\n\t\tif ((r->flags & WPA_SCAN_ASSOCIATED) &&\n\t\t    !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) {\n\t\t\tos_free(res->res[i]);\n\t\t\tres->res[i] = r;\n\t\t} else\n\t\t\tos_free(r);\n\t\treturn NL_SKIP;\n\t}\n\n\ttmp = os_realloc(res->res,\n\t\t\t (res->num + 1) * sizeof(struct wpa_scan_res *));\n\tif (tmp == NULL) {\n\t\tos_free(r);\n\t\treturn NL_SKIP;\n\t}\n\ttmp[res->num++] = r;\n\tres->res = tmp;\n\n\treturn NL_SKIP;\n}\n\n\nstatic void clear_state_mismatch(struct wpa_driver_capwap_data *drv,\n\t\t\t\t const u8 *addr)\n{\n\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Clear possible state \"\n\t\t\t   \"mismatch (\" MACSTR \")\", MAC2STR(addr));\n\t\twpa_driver_capwap_mlme(drv, addr,\n\t\t\t\t\tNL80211_CMD_DEAUTHENTICATE,\n\t\t\t\t\tWLAN_REASON_PREV_AUTH_NOT_VALID, 1);\n\t}\n}\n\n\nstatic void wpa_driver_capwap_check_bss_status(\n\tstruct wpa_driver_capwap_data *drv, struct wpa_scan_results *res)\n{\n\tsize_t i;\n\n\tfor (i = 0; i < res->num; i++) {\n\t\tstruct wpa_scan_res *r = res->res[i];\n\t\tif (r->flags & WPA_SCAN_AUTHENTICATED) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Scan results \"\n\t\t\t\t   \"indicates BSS status with \" MACSTR\n\t\t\t\t   \" as authenticated\",\n\t\t\t\t   MAC2STR(r->bssid));\n\t\t\tif (is_sta_interface(drv->nlmode) &&\n\t\t\t    os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&\n\t\t\t    os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=\n\t\t\t    0) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Unknown BSSID\"\n\t\t\t\t\t   \" in local state (auth=\" MACSTR\n\t\t\t\t\t   \" assoc=\" MACSTR \")\",\n\t\t\t\t\t   MAC2STR(drv->auth_bssid),\n\t\t\t\t\t   MAC2STR(drv->bssid));\n\t\t\t\tclear_state_mismatch(drv, r->bssid);\n\t\t\t}\n\t\t}\n\n\t\tif (r->flags & WPA_SCAN_ASSOCIATED) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Scan results \"\n\t\t\t\t   \"indicate BSS status with \" MACSTR\n\t\t\t\t   \" as associated\",\n\t\t\t\t   MAC2STR(r->bssid));\n\t\t\tif (is_sta_interface(drv->nlmode) &&\n\t\t\t    !drv->associated) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Local state \"\n\t\t\t\t\t   \"(not associated) does not match \"\n\t\t\t\t\t   \"with BSS state\");\n\t\t\t\tclear_state_mismatch(drv, r->bssid);\n\t\t\t} else if (is_sta_interface(drv->nlmode) &&\n\t\t\t\t   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=\n\t\t\t\t   0) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Local state \"\n\t\t\t\t\t   \"(associated with \" MACSTR \") does \"\n\t\t\t\t\t   \"not match with BSS state\",\n\t\t\t\t\t   MAC2STR(drv->bssid));\n\t\t\t\tclear_state_mismatch(drv, r->bssid);\n\t\t\t\tclear_state_mismatch(drv, drv->bssid);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nstatic struct wpa_scan_results *\ncapwap_get_scan_results(struct wpa_driver_capwap_data *drv)\n{\n\tstruct nl_msg *msg;\n\tstruct wpa_scan_results *res;\n\tint ret;\n\tstruct capwap_bss_info_arg arg;\n\n\tres = os_zalloc(sizeof(*res));\n\tif (res == NULL)\n\t\treturn NULL;\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\targ.drv = drv;\n\targ.res = res;\n\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Received scan results (%lu \"\n\t\t\t   \"BSSes)\", (unsigned long) res->num);\n\t\tcapwap_get_noise_for_scan_results(drv, res);\n\t\treturn res;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n\t\t   \"(%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_scan_results_free(res);\n\treturn NULL;\n}\n\n\n/**\n * wpa_driver_capwap_get_scan_results - Fetch the latest scan results\n * @priv: Pointer to private wext data from wpa_driver_capwap_init()\n * Returns: Scan results on success, -1 on failure\n */\nstatic struct wpa_scan_results *\nwpa_driver_capwap_get_scan_results(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct wpa_scan_results *res;\n\n\tres = capwap_get_scan_results(drv);\n\tif (res)\n\t\twpa_driver_capwap_check_bss_status(drv, res);\n\treturn res;\n}\n\n\nstatic void capwap_dump_scan(struct wpa_driver_capwap_data *drv)\n{\n\tstruct wpa_scan_results *res;\n\tsize_t i;\n\n\tres = capwap_get_scan_results(drv);\n\tif (res == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to get scan results\");\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result dump\");\n\tfor (i = 0; i < res->num; i++) {\n\t\tstruct wpa_scan_res *r = res->res[i];\n\t\twpa_printf(MSG_DEBUG, \"capwap: %d/%d \" MACSTR \"%s%s\",\n\t\t\t   (int) i, (int) res->num, MAC2STR(r->bssid),\n\t\t\t   r->flags & WPA_SCAN_AUTHENTICATED ? \" [auth]\" : \"\",\n\t\t\t   r->flags & WPA_SCAN_ASSOCIATED ? \" [assoc]\" : \"\");\n\t}\n\n\twpa_scan_results_free(res);\n}\n\n\nstatic int wpa_driver_capwap_set_key(const char *ifname, void *priv,\n\t\t\t\t      enum wpa_alg alg, const u8 *addr,\n\t\t\t\t      int key_idx, int set_tx,\n\t\t\t\t      const u8 *seq, size_t seq_len,\n\t\t\t\t      const u8 *key, size_t key_len)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ifindex = if_nametoindex(ifname);\n\tstruct nl_msg *msg;\n\tint ret;\n\n\twpa_printf(MSG_DEBUG, \"%s: ifindex=%d alg=%d addr=%p key_idx=%d \"\n\t\t   \"set_tx=%d seq_len=%lu key_len=%lu\",\n\t\t   __func__, ifindex, alg, addr, key_idx, set_tx,\n\t\t   (unsigned long) seq_len, (unsigned long) key_len);\n#ifdef CONFIG_TDLS\n\tif (key_idx == -1)\n\t\tkey_idx = 0;\n#endif /* CONFIG_TDLS */\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tif (alg == WPA_ALG_NONE) {\n\t\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);\n\t} else {\n\t\tcapwap_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);\n\t\tNLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);\n\t\tswitch (alg) {\n\t\tcase WPA_ALG_WEP:\n\t\t\tif (key_len == 5)\n\t\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\t\telse\n\t\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\t\t\tbreak;\n\t\tcase WPA_ALG_TKIP:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_TKIP);\n\t\t\tbreak;\n\t\tcase WPA_ALG_CCMP:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_CCMP);\n\t\t\tbreak;\n\t\tcase WPA_ALG_IGTK:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_AES_CMAC);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\twpa_printf(MSG_ERROR, \"%s: Unsupported encryption \"\n\t\t\t\t   \"algorithm %d\", __func__, alg);\n\t\t\tnlmsg_free(msg);\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tif (seq && seq_len)\n\t\tNLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);\n\n\tif (addr && !is_broadcast_ether_addr(addr)) {\n\t\twpa_printf(MSG_DEBUG, \"   addr=\" MACSTR, MAC2STR(addr));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\n\t\tif (alg != WPA_ALG_WEP && key_idx && !set_tx) {\n\t\t\twpa_printf(MSG_DEBUG, \"   RSN IBSS RX GTK\");\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE,\n\t\t\t\t    NL80211_KEYTYPE_GROUP);\n\t\t}\n\t} else if (addr && is_broadcast_ether_addr(addr)) {\n\t\tstruct nl_msg *types;\n\t\tint err;\n\t\twpa_printf(MSG_DEBUG, \"   broadcast key\");\n\t\ttypes = nlmsg_alloc();\n\t\tif (!types)\n\t\t\tgoto nla_put_failure;\n\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);\n\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n\t\t\t\t     types);\n\t\tnlmsg_free(types);\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t}\n\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)\n\t\tret = 0;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: set_key failed; err=%d %s)\",\n\t\t\t   ret, strerror(-ret));\n\n\t/*\n\t * If we failed or don't need to set the default TX key (below),\n\t * we're done here.\n\t */\n\tif (ret || !set_tx || alg == WPA_ALG_NONE)\n\t\treturn ret;\n\tif (is_ap_interface(drv->nlmode) && addr &&\n\t    !is_broadcast_ether_addr(addr))\n\t\treturn ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);\n\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\tif (alg == WPA_ALG_IGTK)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT);\n\telse\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);\n\tif (addr && is_broadcast_ether_addr(addr)) {\n\t\tstruct nl_msg *types;\n\t\tint err;\n\t\ttypes = nlmsg_alloc();\n\t\tif (!types)\n\t\t\tgoto nla_put_failure;\n\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);\n\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n\t\t\t\t     types);\n\t\tnlmsg_free(types);\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t} else if (addr) {\n\t\tstruct nl_msg *types;\n\t\tint err;\n\t\ttypes = nlmsg_alloc();\n\t\tif (!types)\n\t\t\tgoto nla_put_failure;\n\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST);\n\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n\t\t\t\t     types);\n\t\tnlmsg_free(types);\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif (ret == -ENOENT)\n\t\tret = 0;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: set_key default failed; \"\n\t\t\t   \"err=%d %s)\", ret, strerror(-ret));\n\treturn ret;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,\n\t\t      int key_idx, int defkey,\n\t\t      const u8 *seq, size_t seq_len,\n\t\t      const u8 *key, size_t key_len)\n{\n\tstruct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);\n\tif (!key_attr)\n\t\treturn -1;\n\n\tif (defkey && alg == WPA_ALG_IGTK)\n\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);\n\telse if (defkey)\n\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);\n\n\tNLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);\n\n\tswitch (alg) {\n\tcase WPA_ALG_WEP:\n\t\tif (key_len == 5)\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\telse\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\t\tbreak;\n\tcase WPA_ALG_TKIP:\n\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP);\n\t\tbreak;\n\tcase WPA_ALG_CCMP:\n\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP);\n\t\tbreak;\n\tcase WPA_ALG_IGTK:\n\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t    WLAN_CIPHER_SUITE_AES_CMAC);\n\t\tbreak;\n\tdefault:\n\t\twpa_printf(MSG_ERROR, \"%s: Unsupported encryption \"\n\t\t\t   \"algorithm %d\", __func__, alg);\n\t\treturn -1;\n\t}\n\n\tif (seq && seq_len)\n\t\tNLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);\n\n\tNLA_PUT(msg, NL80211_KEY_DATA, key_len, key);\n\n\tnla_nest_end(msg, key_attr);\n\n\treturn 0;\n nla_put_failure:\n\treturn -1;\n}\n\n\nstatic int capwap_set_conn_keys(struct wpa_driver_associate_params *params,\n\t\t\t\t struct nl_msg *msg)\n{\n\tint i, privacy = 0;\n\tstruct nlattr *nl_keys, *nl_key;\n\n\tfor (i = 0; i < 4; i++) {\n\t\tif (!params->wep_key[i])\n\t\t\tcontinue;\n\t\tprivacy = 1;\n\t\tbreak;\n\t}\n\tif (params->wps == WPS_MODE_PRIVACY)\n\t\tprivacy = 1;\n\tif (params->pairwise_suite &&\n\t    params->pairwise_suite != WPA_CIPHER_NONE)\n\t\tprivacy = 1;\n\n\tif (!privacy)\n\t\treturn 0;\n\n\tNLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);\n\n\tnl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);\n\tif (!nl_keys)\n\t\tgoto nla_put_failure;\n\n\tfor (i = 0; i < 4; i++) {\n\t\tif (!params->wep_key[i])\n\t\t\tcontinue;\n\n\t\tnl_key = nla_nest_start(msg, i);\n\t\tif (!nl_key)\n\t\t\tgoto nla_put_failure;\n\n\t\tNLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],\n\t\t\tparams->wep_key[i]);\n\t\tif (params->wep_key_len[i] == 5)\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\telse\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\n\t\tNLA_PUT_U8(msg, NL80211_KEY_IDX, i);\n\n\t\tif (i == params->wep_tx_keyidx)\n\t\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);\n\n\t\tnla_nest_end(msg, nl_key);\n\t}\n\tnla_nest_end(msg, nl_keys);\n\n\treturn 0;\n\nnla_put_failure:\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_mlme(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   const u8 *addr, int cmd, u16 reason_code,\n\t\t\t\t   int local_state_change)\n{\n\n\tint ret = -1;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, cmd);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tif (local_state_change)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME command failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t const u8 *addr, int reason_code)\n{\n\twpa_printf(MSG_DEBUG, \"%s(addr=\" MACSTR \" reason_code=%d)\",\n\t\t   __func__, MAC2STR(addr), reason_code);\n\tdrv->associated = 0;\n\treturn wpa_driver_capwap_mlme(drv, addr, NL80211_CMD_DISCONNECT,\n\t\t\t\t       reason_code, 0);\n}\n\n\nstatic int wpa_driver_capwap_deauthenticate(void *priv, const u8 *addr,\n\t\t\t\t\t     int reason_code)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))\n\t\treturn wpa_driver_capwap_disconnect(drv, addr, reason_code);\n\twpa_printf(MSG_DEBUG, \"%s(addr=\" MACSTR \" reason_code=%d)\",\n\t\t   __func__, MAC2STR(addr), reason_code);\n\tdrv->associated = 0;\n\tif (drv->nlmode == NL80211_IFTYPE_ADHOC)\n\t\treturn capwap_leave_ibss(drv);\n\treturn wpa_driver_capwap_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,\n\t\t\t\t       reason_code, 0);\n}\n\n\nstatic int wpa_driver_capwap_disassociate(void *priv, const u8 *addr,\n\t\t\t\t\t   int reason_code)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))\n\t\treturn wpa_driver_capwap_disconnect(drv, addr, reason_code);\n\twpa_printf(MSG_DEBUG, \"%s\", __func__);\n\tdrv->associated = 0;\n\treturn wpa_driver_capwap_mlme(drv, addr, NL80211_CMD_DISASSOCIATE,\n\t\t\t\t       reason_code, 0);\n}\n\n\nstatic int wpa_driver_capwap_authenticate(\n\tvoid *priv, struct wpa_driver_auth_params *params)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1, i;\n\tstruct nl_msg *msg;\n\tenum nl80211_auth_type type;\n\tenum nl80211_iftype nlmode;\n\tint count = 0;\n\n\tdrv->associated = 0;\n\tos_memset(drv->auth_bssid, 0, ETH_ALEN);\n\t/* FIX: IBSS mode */\n\tnlmode = params->p2p ?\n\t\tNL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;\n\tif (drv->nlmode != nlmode &&\n\t    wpa_driver_capwap_set_mode(priv, nlmode) < 0)\n\t\treturn -1;\n\nretry:\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Authenticate (ifindex=%d)\",\n\t\t   drv->ifindex);\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);\n\n\tfor (i = 0; i < 4; i++) {\n\t\tif (!params->wep_key[i])\n\t\t\tcontinue;\n\t\twpa_driver_capwap_set_key(bss->ifname, priv, WPA_ALG_WEP,\n\t\t\t\t\t   NULL, i,\n\t\t\t\t\t   i == params->wep_tx_keyidx, NULL, 0,\n\t\t\t\t\t   params->wep_key[i],\n\t\t\t\t\t   params->wep_key_len[i]);\n\t\tif (params->wep_tx_keyidx != i)\n\t\t\tcontinue;\n\t\tif (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,\n\t\t\t       params->wep_key[i], params->wep_key_len[i])) {\n\t\t\tnlmsg_free(msg);\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tif (params->bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n\t}\n\tif (params->freq) {\n\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\t}\n\tif (params->ssid) {\n\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t\t  params->ssid, params->ssid_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n\t\t\tparams->ssid);\n\t}\n\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->ie, params->ie_len);\n\tif (params->ie)\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie);\n\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n\t\ttype = NL80211_AUTHTYPE_OPEN_SYSTEM;\n\telse if (params->auth_alg & WPA_AUTH_ALG_SHARED)\n\t\ttype = NL80211_AUTHTYPE_SHARED_KEY;\n\telse if (params->auth_alg & WPA_AUTH_ALG_LEAP)\n\t\ttype = NL80211_AUTHTYPE_NETWORK_EAP;\n\telse if (params->auth_alg & WPA_AUTH_ALG_FT)\n\t\ttype = NL80211_AUTHTYPE_FT;\n\telse\n\t\tgoto nla_put_failure;\n\twpa_printf(MSG_DEBUG, \"  * Auth Type %d\", type);\n\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);\n\tif (params->local_state_change) {\n\t\twpa_printf(MSG_DEBUG, \"  * Local state change only\");\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME command failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tcount++;\n\t\tif (ret == -EALREADY && count == 1 && params->bssid &&\n\t\t    !params->local_state_change) {\n\t\t\t/*\n\t\t\t * mac80211 does not currently accept new\n\t\t\t * authentication if we are already authenticated. As a\n\t\t\t * workaround, force deauthentication and try again.\n\t\t\t */\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Retry authentication \"\n\t\t\t\t   \"after forced deauthentication\");\n\t\t\twpa_driver_capwap_deauthenticate(\n\t\t\t\tbss, params->bssid,\n\t\t\t\tWLAN_REASON_PREV_AUTH_NOT_VALID);\n\t\t\tnlmsg_free(msg);\n\t\t\tgoto retry;\n\t\t}\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Authentication request send \"\n\t\t   \"successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstruct phy_info_arg {\n\tu16 *num_modes;\n\tstruct hostapd_hw_modes *modes;\n};\n\nstatic int phy_info_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb_msg[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct phy_info_arg *phy_info = arg;\n\n\tstruct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];\n\n\tstruct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];\n\tstatic struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {\n\t\t[NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },\n\t\t[NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },\n\t};\n\n\tstruct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];\n\tstatic struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {\n\t\t[NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },\n\t\t[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG },\n\t};\n\n\tstruct nlattr *nl_band;\n\tstruct nlattr *nl_freq;\n\tstruct nlattr *nl_rate;\n\tint rem_band, rem_freq, rem_rate;\n\tstruct hostapd_hw_modes *mode;\n\tint idx, mode_is_set;\n\n\tnla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (!tb_msg[NL80211_ATTR_WIPHY_BANDS])\n\t\treturn NL_SKIP;\n\n\tnla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {\n\t\tmode = os_realloc(phy_info->modes, (*phy_info->num_modes + 1) * sizeof(*mode));\n\t\tif (!mode)\n\t\t\treturn NL_SKIP;\n\t\tphy_info->modes = mode;\n\n\t\tmode_is_set = 0;\n\n\t\tmode = &phy_info->modes[*(phy_info->num_modes)];\n\t\tmemset(mode, 0, sizeof(*mode));\n\t\tmode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN;\n\t\t*(phy_info->num_modes) += 1;\n\n\t\tnla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),\n\t\t\t  nla_len(nl_band), NULL);\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {\n\t\t\tmode->ht_capab = nla_get_u16(\n\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_CAPA]);\n\t\t}\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) {\n\t\t\tmode->a_mpdu_params |= nla_get_u8(\n\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) &\n\t\t\t\t0x03;\n\t\t}\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) {\n\t\t\tmode->a_mpdu_params |= nla_get_u8(\n\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) <<\n\t\t\t\t2;\n\t\t}\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] &&\n\t\t    nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])) {\n\t\t\tu8 *mcs;\n\t\t\tmcs = nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);\n\t\t\tos_memcpy(mode->mcs_set, mcs, 16);\n\t\t}\n\n\t\tnla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {\n\t\t\tnla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),\n\t\t\t\t  nla_len(nl_freq), freq_policy);\n\t\t\tif (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])\n\t\t\t\tcontinue;\n\t\t\tmode->num_channels++;\n\t\t}\n\n\t\tmode->channels = os_zalloc(mode->num_channels * sizeof(struct hostapd_channel_data));\n\t\tif (!mode->channels)\n\t\t\treturn NL_SKIP;\n\n\t\tidx = 0;\n\n\t\tnla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {\n\t\t\tnla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),\n\t\t\t\t  nla_len(nl_freq), freq_policy);\n\t\t\tif (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])\n\t\t\t\tcontinue;\n\n\t\t\tmode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);\n\t\t\tmode->channels[idx].flag = 0;\n\n\t\t\tif (!mode_is_set) {\n\t\t\t\t/* crude heuristic */\n\t\t\t\tif (mode->channels[idx].freq < 4000)\n\t\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n\t\t\t\telse\n\t\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211A;\n\t\t\t\tmode_is_set = 1;\n\t\t\t}\n\n\t\t\t/* crude heuristic */\n\t\t\tif (mode->channels[idx].freq < 4000)\n\t\t\t\tif (mode->channels[idx].freq == 2484)\n\t\t\t\t\tmode->channels[idx].chan = 14;\n\t\t\t\telse\n\t\t\t\t\tmode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5;\n\t\t\telse\n\t\t\t\tmode->channels[idx].chan = mode->channels[idx].freq/5 - 1000;\n\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_DISABLED;\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_PASSIVE_SCAN;\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_NO_IBSS;\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_RADAR;\n\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] &&\n\t\t\t    !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])\n\t\t\t\tmode->channels[idx].max_tx_power =\n\t\t\t\t\tnla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100;\n\n\t\t\tidx++;\n\t\t}\n\n\t\tnla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {\n\t\t\tnla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),\n\t\t\t\t  nla_len(nl_rate), rate_policy);\n\t\t\tif (!tb_rate[NL80211_BITRATE_ATTR_RATE])\n\t\t\t\tcontinue;\n\t\t\tmode->num_rates++;\n\t\t}\n\n\t\tmode->rates = os_zalloc(mode->num_rates * sizeof(int));\n\t\tif (!mode->rates)\n\t\t\treturn NL_SKIP;\n\n\t\tidx = 0;\n\n\t\tnla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {\n\t\t\tnla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),\n\t\t\t\t  nla_len(nl_rate), rate_policy);\n\t\t\tif (!tb_rate[NL80211_BITRATE_ATTR_RATE])\n\t\t\t\tcontinue;\n\t\t\tmode->rates[idx] = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]);\n\n\t\t\t/* crude heuristic */\n\t\t\tif (mode->mode == HOSTAPD_MODE_IEEE80211B &&\n\t\t\t    mode->rates[idx] > 200)\n\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211G;\n\n\t\t\tidx++;\n\t\t}\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic struct hostapd_hw_modes *\nwpa_driver_capwap_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes)\n{\n\n\tu16 m;\n\tstruct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;\n\tint i, mode11g_idx = -1;\n\tint j;\n\n\n\t/* If only 802.11g mode is included, use it to construct matching\n\t * 802.11b mode data. */\n\n\tfor (m = 0; m < *num_modes; m++) {\n\t\twpa_printf(MSG_DEBUG,\"*** 2.2 %d\\n\",m);\n\t\tif (modes[m].mode == HOSTAPD_MODE_IEEE80211B)\n\t\t\treturn modes; /* 802.11b already included */\n\t\tif (modes[m].mode == HOSTAPD_MODE_IEEE80211G)\n\t\t\tmode11g_idx = m;\n\t}\n\n\tif (mode11g_idx < 0)\n\t\treturn modes; /* 2.4 GHz band not supported at all */\n\n\tnmodes = os_realloc(modes, (*num_modes + 1) * sizeof(*nmodes));\n\tif (nmodes == NULL)\n\t\treturn modes; /* Could not add 802.11b mode */\n\n\tmode = &nmodes[*num_modes];\n\tos_memset(mode, 0, sizeof(*mode));\n\t(*num_modes)++;\n\tmodes = nmodes;\n\n\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n\n\tmode11g = &modes[mode11g_idx];\n\tmode->num_channels = mode11g->num_channels;\n\tmode->channels = os_malloc(mode11g->num_channels *\n\t\t\t\t   sizeof(struct hostapd_channel_data));\n\tif (mode->channels == NULL) {\n\t\t(*num_modes)--;\n\t\treturn modes; /* Could not add 802.11b mode */\n\t}\n\tos_memcpy(mode->channels, mode11g->channels,\n\t\t  mode11g->num_channels * sizeof(struct hostapd_channel_data));\n\n\tmode->num_rates = 0;\n\tmode->rates = os_malloc(4 * sizeof(int));\n\tif (mode->rates == NULL) {\n\t\tos_free(mode->channels);\n\t\t(*num_modes)--;\n\t\treturn modes; /* Could not add 802.11b mode */\n\t}\n\n\tfor (i = 0; i < mode11g->num_rates; i++) {\n\t\tif (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&\n\t\t    mode11g->rates[i] != 55 && mode11g->rates[i] != 110)\n\t\t\tcontinue;\n\t\tmode->rates[mode->num_rates] = mode11g->rates[i];\n\t\tmode->num_rates++;\n\t\tif (mode->num_rates == 4)\n\t\t\tbreak;\n\t}\n\n\tif (mode->num_rates == 0) {\n\t\tos_free(mode->channels);\n\t\tos_free(mode->rates);\n\t\t(*num_modes)--;\n\t\treturn modes; /* No 802.11b rates */\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Added 802.11b mode based on 802.11g information\");\n\n\twpa_printf(MSG_DEBUG,\"*** Num_channels:%d Num_rates:%d capab:%d flags:%d MODE:%d mpdu:%02X\",modes->num_channels,modes->num_rates,modes->ht_capab,modes->flags,modes->mode,modes->a_mpdu_params);\n\n\tfor(j=0;j < 16;j++){\n\t\twpa_printf(MSG_DEBUG,\"%02X \",modes->mcs_set[j]);\n\t}\n\n\tfor(j=0;j < modes->num_channels;j++){\n\t\twpa_printf(MSG_DEBUG,\"*** %d freq:%d flag:%d chan:%d freq:%d maxPower:%02X \",j,modes->channels[j].freq,modes->channels[j].flag,modes->channels[j].chan,modes->channels[j].freq,modes->channels[j].max_tx_power);\n\t}\n\tfor(j=0;j < modes->num_rates;j++){\n\t\twpa_printf(MSG_DEBUG,\"*** %d rate:%d  \",j,modes->rates[j]);\n\t}\n\n\n\treturn modes;\n}\n\n\nstatic void capwap_set_ht40_mode(struct hostapd_hw_modes *mode, int start,\n\t\t\t\t  int end)\n{\n\tint c;\n\n\tfor (c = 0; c < mode->num_channels; c++) {\n\t\tstruct hostapd_channel_data *chan = &mode->channels[c];\n\t\tif (chan->freq - 10 >= start && chan->freq + 10 <= end)\n\t\t\tchan->flag |= HOSTAPD_CHAN_HT40;\n\t}\n}\n\n\nstatic void capwap_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,\n\t\t\t\t      int end)\n{\n\tint c;\n\n\tfor (c = 0; c < mode->num_channels; c++) {\n\t\tstruct hostapd_channel_data *chan = &mode->channels[c];\n\t\tif (!(chan->flag & HOSTAPD_CHAN_HT40))\n\t\t\tcontinue;\n\t\tif (chan->freq - 30 >= start && chan->freq - 10 <= end)\n\t\t\tchan->flag |= HOSTAPD_CHAN_HT40MINUS;\n\t\tif (chan->freq + 10 >= start && chan->freq + 30 <= end)\n\t\t\tchan->flag |= HOSTAPD_CHAN_HT40PLUS;\n\t}\n}\n\n\nstatic void capwap_reg_rule_ht40(struct nlattr *tb[],\n\t\t\t\t  struct phy_info_arg *results)\n{\n\tu32 start, end, max_bw;\n\tu16 m;\n\n\tif (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)\n\t\treturn;\n\n\tstart = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;\n\tend = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;\n\tmax_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;\n\n\twpa_printf(MSG_DEBUG, \"capwap: %u-%u @ %u MHz\",\n\t\t   start, end, max_bw);\n\tif (max_bw < 40)\n\t\treturn;\n\n\tfor (m = 0; m < *results->num_modes; m++) {\n\t\tif (!(results->modes[m].ht_capab &\n\t\t      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))\n\t\t\tcontinue;\n\t\tcapwap_set_ht40_mode(&results->modes[m], start, end);\n\t}\n}\n\n\nstatic void capwap_reg_rule_sec(struct nlattr *tb[],\n\t\t\t\t struct phy_info_arg *results)\n{\n\tu32 start, end, max_bw;\n\tu16 m;\n\n\tif (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)\n\t\treturn;\n\n\tstart = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;\n\tend = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;\n\tmax_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;\n\n\tif (max_bw < 20)\n\t\treturn;\n\n\tfor (m = 0; m < *results->num_modes; m++) {\n\t\tif (!(results->modes[m].ht_capab &\n\t\t      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))\n\t\t\tcontinue;\n\t\tcapwap_set_ht40_mode_sec(&results->modes[m], start, end);\n\t}\n}\n\n\nstatic int capwap_get_reg(struct nl_msg *msg, void *arg)\n{\n\tstruct phy_info_arg *results = arg;\n\tstruct nlattr *tb_msg[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *nl_rule;\n\tstruct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];\n\tint rem_rule;\n\tstatic struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {\n\t\t[NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },\n\t};\n\n\tnla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||\n\t    !tb_msg[NL80211_ATTR_REG_RULES]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No regulatory information \"\n\t\t\t   \"available\");\n\t\treturn NL_SKIP;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Regulatory information - country=%s\",\n\t\t   (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));\n\n\tnla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)\n\t{\n\t\tnla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,\n\t\t\t  nla_data(nl_rule), nla_len(nl_rule), reg_policy);\n\t\tcapwap_reg_rule_ht40(tb_rule, results);\n\t}\n\n\tnla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)\n\t{\n\t\tnla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,\n\t\t\t  nla_data(nl_rule), nla_len(nl_rule), reg_policy);\n\t\tcapwap_reg_rule_sec(tb_rule, results);\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_set_ht40_flags(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct phy_info_arg *results)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_REG);\n\n\treturn send_and_recv_msgs(drv, msg, capwap_get_reg, results);\n}\n\nstatic struct hostapd_hw_modes *\nAC_wpa_driver_capwap_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)\n{\n\tint rate_arrays[8];\n\tint num_rates;\n/*\n\tint num_modes1;\n*/\n\tint i;\n\n\tnum_rates = capability_get_rates(rate_arrays);\n/* capwap FIXME: needed?\n\tnum_modes1 = capability_get_num_modes();\n*/\n\tstruct hostapd_hw_modes *mode;\n\tint clen, rlen;\n\tconst short chan2freq[14] = {\n\t\t2412, 2417, 2422, 2427, 2432, 2437, 2442,\n\t\t2447, 2452, 2457, 2462, 2467, 2472, 2484\n\t};\n\n\tmode = os_zalloc(sizeof(struct hostapd_hw_modes));\n\tif (mode == NULL)\n\t\treturn NULL;\n\n\t*num_modes = 1;\n\t*flags = 0;\n\n\tif(capability_is_B()){\n\t\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n\t}else{\n\t \twpa_printf(MSG_ERROR, \"ERROR AC_wpa_driver_capwap_get_hw_feature_data\\n\");\n\t \texit(1);\n\t}\n\n\tmode->num_channels = capability_get_num_channels();\n\tmode->num_rates = num_rates ;\n\n\tclen = mode->num_channels * sizeof(struct hostapd_channel_data);\n\trlen = mode->num_rates * sizeof(int);\n\n\tmode->channels = os_zalloc(clen);\n\tmode->rates = os_zalloc(rlen);\n\tif (mode->channels == NULL || mode->rates == NULL) {\n\t\tos_free(mode->channels);\n\t\tos_free(mode->rates);\n\t\tos_free(mode);\n\t\treturn NULL;\n\t}\n\n\tfor (i = 0; i < mode->num_channels; i++) {\n\t\tmode->channels[i].chan = i + 1;\n\t\tmode->channels[i].freq = chan2freq[i];\n\t\t/* TODO: Get allowed channel list from the driver */\n\t\tif (i >= 11)\n\t\t\tmode->channels[i].flag = HOSTAPD_CHAN_DISABLED;\n\t}\n\n\tfor( i=0; i<mode->num_rates ; i++){\n\n\t\tif( rate_arrays[i] < 0 )\n\t\t\tmode->rates[i] = -1 * rate_arrays[i];\n\t\telse\n\t\t\tmode->rates[i] =  rate_arrays[i];\n\n\t}\n\n\treturn mode;\n\n}\n\nstatic struct hostapd_hw_modes *\nwpa_driver_capwap_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t1.wpa_driver_capwap_get_hw_feature_data \");\n\n\treturn AC_wpa_driver_capwap_get_hw_feature_data(priv,num_modes,flags);\n\n}\n\n\nstatic int wpa_driver_capwap_send_frame(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t const void *data, size_t len,\n\t\t\t\t\t int encrypt)\n{\n\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t\t\t\t\t\t1.wpa_driver_capwap_send_frame \");\n\tunsigned char buf[3000];\n\n\t__u8 rtap_hdr[] = {\n\t\t0x00, 0x00, /* radiotap version */\n\t\t0x0e, 0x00, /* radiotap length */\n\t\t0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */\n\t\tIEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */\n\t\t0x00,       /* padding */\n\t\t0x00, 0x00, /* RX and TX flags to indicate that */\n\t\t0x00, 0x00, /* this is the injected frame directly */\n\t};\n\tstruct iovec iov[2] = {\n\t\t{\n\t\t\t.iov_base = &rtap_hdr,\n\t\t\t.iov_len = sizeof(rtap_hdr),\n\t\t},\n\t\t{\n\t\t\t.iov_base = (void *) data,\n\t\t\t.iov_len = len,\n\t\t}\n\t};\n\n\tstruct msghdr msg = {\n\t\t.msg_name = NULL,\n\t\t.msg_namelen = 0,\n\t\t.msg_iov = iov,\n\t\t.msg_iovlen = 2,\n\t\t.msg_control = NULL,\n\t\t.msg_controllen = 0,\n\t\t.msg_flags = 0,\n\t};\n\tint res;\n\n\tif (encrypt)\n\t\trtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;\n\n\n\n\t\tmemcpy(buf,(u8 *)(data),len);\n\t\t//AC_handle_send_data_to_WTP(buf, len, generic_ac_info.own_mac_addr);\n\n\t\t//Switch_Mac_Address_AC_to_WTP(buf, generic_ac_info.own_mac_addr);\n\t\tipc_send_80211_to_wtp(generic_ac_info.fd_ipc, buf, len);\n\n\t\treturn 0;\n\n\n\tres = sendmsg(drv->monitor_sock, &msg, 0);\n\tif (res < 0) {\n\t\twpa_printf(MSG_INFO, \"capwap: sendmsg: %s\", strerror(errno));\n\t\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\nstatic int wpa_driver_capwap_send_mlme(void *priv, const u8 *data,\n\t\t\t\t\tsize_t data_len)\n{\n\t//wpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t\t\t\t\t1.wpa_driver_capwap_send_mlme \");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct ieee80211_mgmt *mgmt;\n\tint encrypt = 1;\n\tu16 fc;\n\n\tmgmt = (struct ieee80211_mgmt *) data;\n\n\n\tfc = le_to_host16(mgmt->frame_control);\n\n\tif (is_sta_interface(drv->nlmode) &&\n\t    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&\n\t    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {\n\t\t/*\n\t\t * The use of last_mgmt_freq is a bit of a hack,\n\t\t * but it works due to the single-threaded nature\n\t\t * of wpa_supplicant.\n\t\t */\n\t\treturn capwap_send_frame_cmd(drv, drv->last_mgmt_freq, 0,\n\t\t\t\t\t      data, data_len, NULL, 1);\n\t}\n\n\tif (drv->no_monitor_iface_capab && is_ap_interface(drv->nlmode)) {\n\t\treturn capwap_send_frame_cmd(drv, drv->ap_oper_freq, 0,\n\t\t\t\t\t      data, data_len,\n\t\t\t\t\t      &drv->send_action_cookie, 0);\n\t}\n\n\tif (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&\n\t    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {\n\t\t/*\n\t\t * Only one of the authentication frame types is encrypted.\n\t\t * In order for static WEP encryption to work properly (i.e.,\n\t\t * to not encrypt the frame), we need to tell mac80211 about\n\t\t * the frames that must not be encrypted.\n\t\t */\n\t\tu16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);\n\t\tu16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);\n\t\tif (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)\n\t\t\tencrypt = 0;\n\t}\n\n\treturn wpa_driver_capwap_send_frame(drv, data, data_len, encrypt);\n}\n\n\nstatic int capwap_set_ap_isolate(struct i802_bss *bss, int enabled)\n{\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\tNLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, enabled);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\treturn -ENOBUFS;\n}\n\n\nstatic int capwap_set_bss(struct i802_bss *bss, int cts, int preamble,\n\t\t\t   int slot, int ht_opmode)\n{\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);\n\n\tif (cts >= 0)\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);\n\tif (preamble >= 0)\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);\n\tif (slot >= 0)\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);\n\tif (ht_opmode >= 0)\n\t\tNLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_set_ap(void *priv,\n\t\t\t\t     struct wpa_driver_ap_params *params)\n{\n\twpa_printf(MSG_DEBUG, \"> wpa_driver_capwap_set_ap \\n\");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tu8 cmd = NL80211_CMD_NEW_BEACON;\n\tint ret;\n\tint beacon_set;\n\tint ifindex = if_nametoindex(bss->ifname);\n\tint num_suites;\n\tu32 suites[10];\n\tu32 ver;\n\n\tbeacon_set = bss->beacon_set;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Set beacon (beacon_set=%d)\",\n\t\t   beacon_set);\n\tif (beacon_set)\n\t\tcmd = NL80211_CMD_SET_BEACON;\n\n\tcapwap_cmd(drv, msg, 0, cmd);\n\tNLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);\n\tNLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);\n\tNLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);\n\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n\t\tparams->ssid);\n\tswitch (params->hide_ssid) {\n\tcase NO_SSID_HIDING:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n\t\t\t    NL80211_HIDDEN_SSID_NOT_IN_USE);\n\t\tbreak;\n\tcase HIDDEN_SSID_ZERO_LEN:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n\t\t\t    NL80211_HIDDEN_SSID_ZERO_LEN);\n\t\tbreak;\n\tcase HIDDEN_SSID_ZERO_CONTENTS:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n\t\t\t    NL80211_HIDDEN_SSID_ZERO_CONTENTS);\n\t\tbreak;\n\t}\n\n\n\n\tif (params->privacy)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);\n\tif ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==\n\t    (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {\n\t\t/* Leave out the attribute */\n\t} else if (params->auth_algs & WPA_AUTH_ALG_SHARED)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,\n\t\t\t    NL80211_AUTHTYPE_SHARED_KEY);\n\telse\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,\n\t\t\t    NL80211_AUTHTYPE_OPEN_SYSTEM);\n\n\tver = 0;\n\tif (params->wpa_version & WPA_PROTO_WPA)\n\t\tver |= NL80211_WPA_VERSION_1;\n\tif (params->wpa_version & WPA_PROTO_RSN)\n\t\tver |= NL80211_WPA_VERSION_2;\n\tif (ver)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);\n\n\tnum_suites = 0;\n\tif (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)\n\t\tsuites[num_suites++] = WLAN_AKM_SUITE_8021X;\n\tif (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)\n\t\tsuites[num_suites++] = WLAN_AKM_SUITE_PSK;\n\tif (num_suites) {\n\t\tNLA_PUT(msg, NL80211_ATTR_AKM_SUITES,\n\t\t\tnum_suites * sizeof(u32), suites);\n\t}\n\n\tnum_suites = 0;\n\tif (params->pairwise_ciphers & WPA_CIPHER_CCMP)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;\n\tif (params->pairwise_ciphers & WPA_CIPHER_TKIP)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;\n\tif (params->pairwise_ciphers & WPA_CIPHER_WEP104)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;\n\tif (params->pairwise_ciphers & WPA_CIPHER_WEP40)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;\n\tif (num_suites) {\n\t\tNLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,\n\t\t\tnum_suites * sizeof(u32), suites);\n\t}\n\n\tswitch (params->group_cipher) {\n\tcase WPA_CIPHER_CCMP:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_CCMP);\n\t\tbreak;\n\tcase WPA_CIPHER_TKIP:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_TKIP);\n\t\tbreak;\n\tcase WPA_CIPHER_WEP104:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\t\tbreak;\n\tcase WPA_CIPHER_WEP40:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\tbreak;\n\t}\n\n\tif (params->beacon_ies) {\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),\n\t\t\twpabuf_head(params->beacon_ies));\n\t}\n\tif (params->proberesp_ies) {\n\t\tNLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,\n\t\t\twpabuf_len(params->proberesp_ies),\n\t\t\twpabuf_head(params->proberesp_ies));\n\t}\n\tif (params->assocresp_ies) {\n\t\tNLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,\n\t\t\twpabuf_len(params->assocresp_ies),\n\t\t\twpabuf_head(params->assocresp_ies));\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Beacon set failed: %d (%s)\",\n\t\t\t   ret, strerror(-ret));\n\t} else {\n\t\tbss->beacon_set = 1;\n\t\tret = capwap_set_ap_isolate(bss, params->isolate);\n\t\tif (!params->isolate && ret) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore AP isolation \"\n\t\t\t\t   \"configuration error since isolation is \"\n\t\t\t\t   \"not used\");\n\t\t\tret = 0;\n\t\t}\n\n\t\tcapwap_set_bss(bss, params->cts_protect, params->preamble,\n\t\t\t\tparams->short_slot_time, params->ht_opmode);\n\t}\n\n\twpa_printf(MSG_DEBUG, \"=== (P) privacy: %d\\n\",params->privacy);\n\twpa_printf(MSG_DEBUG, \"=== (T) short_slot_time: %d\\n\",params->short_slot_time);\n\twpa_printf(MSG_DEBUG, \"=== (S) preamble: %d\\n\",params->preamble);\n\n\tprep_beacon(generic_ac_info.fd_ipc,drv->ctx,params);\n\n\t//ipc_send_ADD_WLAN(generic_ac_info.fd_ipc, params->ssid, params->ssid_len);\n\n\treturn ret;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_set_freq(struct wpa_driver_capwap_data *drv,\n\t\t\t\t       int freq, int ht_enabled,\n\t\t\t\t       int sec_channel_offset)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t\t1.wpa_driver_capwap_set_freq\");\n\treturn 0;\n\n}\n\n\nstatic u32 sta_flags_capwap(int flags)\n{\n\tu32 f = 0;\n\n\tif (flags & WPA_STA_AUTHORIZED)\n\t\tf |= BIT(NL80211_STA_FLAG_AUTHORIZED);\n\tif (flags & WPA_STA_WMM)\n\t\tf |= BIT(NL80211_STA_FLAG_WME);\n\tif (flags & WPA_STA_SHORT_PREAMBLE)\n\t\tf |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);\n\tif (flags & WPA_STA_MFP)\n\t\tf |= BIT(NL80211_STA_FLAG_MFP);\n\tif (flags & WPA_STA_TDLS_PEER)\n\t\tf |= BIT(NL80211_STA_FLAG_TDLS_PEER);\n\n\treturn f;\n}\n\n\nstatic int wpa_driver_capwap_sta_add(void *priv,\n\t\t\t\t      struct hostapd_sta_add_params *params)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tstruct nl80211_sta_flag_update upd;\n\tint ret = -ENOBUFS;\n\n\tif ((params->flags & WPA_STA_TDLS_PEER) &&\n\t    !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n\t\treturn -EOPNOTSUPP;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :\n\t\t    NL80211_CMD_NEW_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);\n\tNLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,\n\t\tparams->supp_rates);\n\tif (!params->set) {\n\t\tNLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);\n\t\tNLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,\n\t\t\t    params->listen_interval);\n\t}\n\tif (params->ht_capabilities) {\n\t\tNLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,\n\t\t\tsizeof(*params->ht_capabilities),\n\t\t\tparams->ht_capabilities);\n\t}\n\n\tos_memset(&upd, 0, sizeof(upd));\n\tupd.mask = sta_flags_capwap(params->flags);\n\tupd.set = upd.mask;\n\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: NL80211_CMD_%s_STATION \"\n\t\t\t   \"result: %d (%s)\", params->set ? \"SET\" : \"NEW\", ret,\n\t\t\t   strerror(-ret));\n\tif (ret == -EEXIST)\n\t\tret = 0;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_sta_remove(void *priv, const u8 *addr)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif (ret == -ENOENT)\n\t\treturn 0;\n\treturn ret;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic void capwap_remove_iface(struct wpa_driver_capwap_data *drv,\n\t\t\t\t int ifidx)\n{\n\tstruct nl_msg *msg;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Remove interface ifindex=%d\", ifidx);\n\n\t/* stop listening for EAPOL on this interface */\n\tdel_ifidx(drv, ifidx);\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);\n\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n\t\treturn;\n\tmsg = NULL;\n nla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_ERROR, \"Failed to remove interface (ifidx=%d)\", ifidx);\n}\n\n\nstatic const char * nl80211_iftype_str(enum nl80211_iftype mode)\n{\n\tswitch (mode) {\n\tcase NL80211_IFTYPE_ADHOC:\n\t\treturn \"ADHOC\";\n\tcase NL80211_IFTYPE_STATION:\n\t\treturn \"STATION\";\n\tcase NL80211_IFTYPE_AP:\n\t\treturn \"AP\";\n\tcase NL80211_IFTYPE_MONITOR:\n\t\treturn \"MONITOR\";\n\tcase NL80211_IFTYPE_P2P_CLIENT:\n\t\treturn \"P2P_CLIENT\";\n\tcase NL80211_IFTYPE_P2P_GO:\n\t\treturn \"P2P_GO\";\n\tdefault:\n\t\treturn \"unknown\";\n\t}\n}\n\n\nstatic int capwap_create_iface_once(struct wpa_driver_capwap_data *drv,\n\t\t\t\t     const char *ifname,\n\t\t\t\t     enum nl80211_iftype iftype,\n\t\t\t\t     const u8 *addr, int wds)\n{\n\twpa_printf(MSG_DEBUG, \"# capwap_create_iface_once\\n\");\n\n\tstruct nl_msg *msg, *flags = NULL;\n\tint ifidx;\n\tint ret = -ENOBUFS;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Create interface iftype %d (%s)\",\n\t\t   iftype, nl80211_iftype_str(iftype));\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);\n\n\tif (iftype == NL80211_IFTYPE_MONITOR) {\n\t\tint err;\n\n\t\tflags = nlmsg_alloc();\n\t\tif (!flags)\n\t\t\tgoto nla_put_failure;\n\n\t\tNLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);\n\n\t\terr = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);\n\n\t\tnlmsg_free(flags);\n\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t} else if (wds) {\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n nla_put_failure:\n\t\tnlmsg_free(msg);\n\t\twpa_printf(MSG_ERROR, \"Failed to create interface %s: %d (%s)\",\n\t\t\t   ifname, ret, strerror(-ret));\n\t\treturn ret;\n\t}\n\n\tifidx = if_nametoindex(ifname);\n\twpa_printf(MSG_DEBUG, \"capwap: New interface %s created: ifindex=%d\",\n\t\t   ifname, ifidx);\n\n\n\t/* start listening for EAPOL on this interface */\n\twpa_printf(MSG_DEBUG, \"start listening for EAPOL on this interface\\n\");\n\tadd_ifidx(drv, ifidx);\n\n\tif (addr && iftype != NL80211_IFTYPE_MONITOR &&\n\t    linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {\n\t\tcapwap_remove_iface(drv, ifidx);\n\t\treturn -1;\n\t}\nwpa_printf(MSG_DEBUG, \"#9 %d\\n\",ifidx);\n\n\treturn ifidx;\n}\n\n\nstatic int capwap_create_iface(struct wpa_driver_capwap_data *drv,\n\t\t\t\tconst char *ifname, enum nl80211_iftype iftype,\n\t\t\t\tconst u8 *addr, int wds)\n{\n\n\tint ret;\n\n\tret = capwap_create_iface_once(drv, ifname, iftype, addr, wds);\n\n\t/* if error occurred and interface exists already */\n\tif (ret == -ENFILE && if_nametoindex(ifname)) {\n\t\twpa_printf(MSG_INFO, \"Try to remove and re-create %s\", ifname);\n\n\t\t/* Try to remove the interface that was already there. */\n\t\tcapwap_remove_iface(drv, if_nametoindex(ifname));\n\n\t\t/* Try to create the interface again */\n\t\tret = capwap_create_iface_once(drv, ifname, iftype, addr,\n\t\t\t\t\t\twds);\n\t}\n\n\tif (ret >= 0 && is_p2p_interface(iftype))\n\t\tcapwap_disable_11b_rates(drv, ret, 1);\n\n\treturn ret;\n}\n\n\nstatic void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)\n{\n\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\tunion wpa_event_data event;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\tos_memset(&event, 0, sizeof(event));\n\tevent.tx_status.type = WLAN_FC_GET_TYPE(fc);\n\tevent.tx_status.stype = WLAN_FC_GET_STYPE(fc);\n\tevent.tx_status.dst = hdr->addr1;\n\tevent.tx_status.data = buf;\n\tevent.tx_status.data_len = len;\n\tevent.tx_status.ack = ok;\n\twpa_supplicant_event(ctx, EVENT_TX_STATUS, &event);\n}\n\n\nstatic void from_unknown_sta(struct wpa_driver_capwap_data *drv,\n\t\t\t     u8 *buf, size_t len)\n{\n\tstruct ieee80211_hdr *hdr = (void *)buf;\n\tu16 fc;\n\tunion wpa_event_data event;\n\n\tif (len < sizeof(*hdr))\n\t\treturn;\n\n\tfc = le_to_host16(hdr->frame_control);\n\n\tos_memset(&event, 0, sizeof(event));\n\tevent.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);\n\tevent.rx_from_unknown.addr = hdr->addr2;\n\tevent.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==\n\t\t(WLAN_FC_FROMDS | WLAN_FC_TODS);\n\twpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);\n}\n\n\nstatic void handle_frame(struct wpa_driver_capwap_data *drv,\n\t\t\t u8 *buf, size_t len, int datarate, int ssi_signal)\n{\n\n\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\tunion wpa_event_data event;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\tswitch (WLAN_FC_GET_TYPE(fc)) {\n\tcase WLAN_FC_TYPE_MGMT:\n\t\tos_memset(&event, 0, sizeof(event));\n\n\t\tevent.rx_mgmt.frame = buf;\n\n\t\tevent.rx_mgmt.frame_len = len;\n\n\t\tevent.rx_mgmt.datarate = datarate;\n\n\t\tevent.rx_mgmt.ssi_signal = ssi_signal;\n\n\t\twpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);\n\t\tbreak;\n\tcase WLAN_FC_TYPE_CTRL:\n\t\t/* can only get here with PS-Poll frames */\n\t\twpa_printf(MSG_DEBUG, \"CTRL\");\n\t\tfrom_unknown_sta(drv, buf, len);\n\t\tbreak;\n\tcase WLAN_FC_TYPE_DATA:\n\t\tfrom_unknown_sta(drv, buf, len);\n\n\t\tbreak;\n\t}\n}\n\n\nstatic void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx){\n\n\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\tint len;\n\tunsigned char buf[3000];\n\tstruct ieee80211_radiotap_iterator iter;\n\tint ret;\n\tint datarate = 0, ssi_signal = 0;\n\tint injected = 0, failed = 0, rxflags = 0;\n\n\tlen = recv(sock, buf, sizeof(buf), 0);\n\n\tif (len < 0) {\n\t\tperror(\"recv\");\n\t\treturn;\n\t}\n\n\tif (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {\n\t\twpa_printf(MSG_DEBUG, \"received invalid radiotap frame\\n\");\n\t\treturn;\n\t}\n\n\twhile (1) {\n\t\tret = ieee80211_radiotap_iterator_next(&iter);\n\t\tif (ret == -ENOENT)\n\t\t\tbreak;\n\t\tif (ret) {\n\t\t\twpa_printf(MSG_DEBUG, \"received invalid radiotap frame (%d)\\n\", ret);\n\t\t\treturn;\n\t\t}\n\t\tswitch (iter.this_arg_index) {\n\t\tcase IEEE80211_RADIOTAP_FLAGS:\n\t\t\tif (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)\n\t\t\t\tlen -= 4;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_RX_FLAGS:\n\t\t\trxflags = 1;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_TX_FLAGS:\n\t\t\tinjected = 1;\n\t\t\tfailed = le_to_host16((*(uint16_t *) iter.this_arg)) &\n\t\t\t\t\tIEEE80211_RADIOTAP_F_TX_FAIL;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_DATA_RETRIES:\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_CHANNEL:\n\t\t\t/* TODO: convert from freq/flags to channel number */\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_RATE:\n\t\t\tdatarate = *iter.this_arg * 5;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_DB_ANTSIGNAL:\n\t\t\tssi_signal = *iter.this_arg;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (rxflags && injected)\n\t\treturn;\n\n\tif (!injected)\n\t\thandle_frame(drv, buf + iter.max_length,\n\t\t\t     len - iter.max_length, datarate, ssi_signal);\n\telse\n\t\thandle_tx_callback(drv->ctx, buf + iter.max_length,\n\t\t\t\t   len - iter.max_length, !failed);\n}\n\n\n/*\n * we post-process the filter code later and rewrite\n * this to the offset to the last instruction\n */\n#define PASS\t0xFF\n#define FAIL\t0xFE\n\nstatic struct sock_filter msock_filter_insns[] = {\n\t/*\n\t * do a little-endian load of the radiotap length field\n\t */\n\t/* load lower byte into A */\n\tBPF_STMT(BPF_LD  | BPF_B | BPF_ABS, 2),\n\t/* put it into X (== index register) */\n\tBPF_STMT(BPF_MISC| BPF_TAX, 0),\n\t/* load upper byte into A */\n\tBPF_STMT(BPF_LD  | BPF_B | BPF_ABS, 3),\n\t/* left-shift it by 8 */\n\tBPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8),\n\t/* or with X */\n\tBPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0),\n\t/* put result into X */\n\tBPF_STMT(BPF_MISC| BPF_TAX, 0),\n\n\t/*\n\t * Allow management frames through, this also gives us those\n\t * management frames that we sent ourselves with status\n\t */\n\t/* load the lower byte of the IEEE 802.11 frame control field */\n\tBPF_STMT(BPF_LD  | BPF_B | BPF_IND, 0),\n\t/* mask off frame type and version */\n\tBPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF),\n\t/* accept frame if it's both 0, fall through otherwise */\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0),\n\n\t/*\n\t * TODO: add a bit to radiotap RX flags that indicates\n\t * that the sending station is not associated, then\n\t * add a filter here that filters on our DA and that flag\n\t * to allow us to deauth frames to that bad station.\n\t *\n\t * For now allow all To DS data frames through.\n\t */\n\t/* load the IEEE 802.11 frame control field */\n\tBPF_STMT(BPF_LD  | BPF_H | BPF_IND, 0),\n\t/* mask off frame type, version and DS status */\n\tBPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03),\n\t/* accept frame if version 0, type 2 and To DS, fall through otherwise\n\t */\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0),\n\n#if 0\n\t/*\n\t * drop non-data frames\n\t */\n\t/* load the lower byte of the frame control field */\n\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 0),\n\t/* mask off QoS bit */\n\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x0c),\n\t/* drop non-data frames */\n\tBPF_JUMP(BPF_JMP  | BPF_JEQ | BPF_K, 8, 0, FAIL),\n#endif\n\t/* load the upper byte of the frame control field */\n\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 1),\n\t/* mask off toDS/fromDS */\n\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x03),\n\t/* accept WDS frames */\n\tBPF_JUMP(BPF_JMP  | BPF_JEQ | BPF_K, 3, PASS, 0),\n\n\t/*\n\t * add header length to index\n\t */\n\t/* load the lower byte of the frame control field */\n\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 0),\n\t/* mask off QoS bit */\n\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x80),\n\t/* right shift it by 6 to give 0 or 2 */\n\tBPF_STMT(BPF_ALU  | BPF_RSH | BPF_K, 6),\n\t/* add data frame header length */\n\tBPF_STMT(BPF_ALU  | BPF_ADD | BPF_K, 24),\n\t/* add index, was start of 802.11 header */\n\tBPF_STMT(BPF_ALU  | BPF_ADD | BPF_X, 0),\n\t/* move to index, now start of LL header */\n\tBPF_STMT(BPF_MISC | BPF_TAX, 0),\n\n\t/*\n\t * Accept empty data frames, we use those for\n\t * polling activity.\n\t */\n\tBPF_STMT(BPF_LD  | BPF_W | BPF_LEN, 0),\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0),\n\n\t/*\n\t * Accept EAPOL frames\n\t */\n\tBPF_STMT(BPF_LD  | BPF_W | BPF_IND, 0),\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL),\n\tBPF_STMT(BPF_LD  | BPF_W | BPF_IND, 4),\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL),\n\n\t/* keep these last two statements or change the code below */\n\t/* return 0 == \"DROP\" */\n\tBPF_STMT(BPF_RET | BPF_K, 0),\n\t/* return ~0 == \"keep all\" */\n\tBPF_STMT(BPF_RET | BPF_K, ~0),\n};\n\nstatic struct sock_fprog msock_filter = {\n\t.len = sizeof(msock_filter_insns)/sizeof(msock_filter_insns[0]),\n\t.filter = msock_filter_insns,\n};\n\n\nstatic int add_monitor_filter(int s)\n{\n\tint idx;\n\n\t/* rewrite all PASS/FAIL jump offsets */\n\tfor (idx = 0; idx < msock_filter.len; idx++) {\n\t\tstruct sock_filter *insn = &msock_filter_insns[idx];\n\n\t\tif (BPF_CLASS(insn->code) == BPF_JMP) {\n\t\t\tif (insn->code == (BPF_JMP|BPF_JA)) {\n\t\t\t\tif (insn->k == PASS)\n\t\t\t\t\tinsn->k = msock_filter.len - idx - 2;\n\t\t\t\telse if (insn->k == FAIL)\n\t\t\t\t\tinsn->k = msock_filter.len - idx - 3;\n\t\t\t}\n\n\t\t\tif (insn->jt == PASS)\n\t\t\t\tinsn->jt = msock_filter.len - idx - 2;\n\t\t\telse if (insn->jt == FAIL)\n\t\t\t\tinsn->jt = msock_filter.len - idx - 3;\n\n\t\t\tif (insn->jf == PASS)\n\t\t\t\tinsn->jf = msock_filter.len - idx - 2;\n\t\t\telse if (insn->jf == FAIL)\n\t\t\t\tinsn->jf = msock_filter.len - idx - 3;\n\t\t}\n\t}\n\n\tif (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER,\n\t\t       &msock_filter, sizeof(msock_filter))) {\n\t\tperror(\"SO_ATTACH_FILTER\");\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\n\nstatic void capwap_remove_monitor_interface(\n\tstruct wpa_driver_capwap_data *drv)\n{\n\treturn ;\n\n}\n\n\nstatic int capwap_create_monitor_interface(struct wpa_driver_capwap_data *drv){\n\twpa_printf(MSG_DEBUG, \"# 8.5   capwap_create_monitor_interface\\n\");\n\t//if(!real)return 0;\n\tchar buf[IFNAMSIZ];\n\tstruct sockaddr_ll ll;\n\tint optval;\n\tsocklen_t optlen;\n\n\tif (os_strncmp(drv->first_bss.ifname, \"p2p-\", 4) == 0) {\n\t\t/*\n\t\t * P2P interface name is of the format p2p-%s-%d. For monitor\n\t\t * interface name corresponding to P2P GO, replace \"p2p-\" with\n\t\t * \"mon-\" to retain the same interface name length and to\n\t\t * indicate that it is a monitor interface.\n\t\t */\n\t\tsnprintf(buf, IFNAMSIZ, \"mon-%s\", drv->first_bss.ifname + 4);\n\t} else {\n\t\t/* Non-P2P interface with AP functionality. */\n\t\tsnprintf(buf, IFNAMSIZ, \"mon.%s\", drv->first_bss.ifname);\n\t}\n\n\tbuf[IFNAMSIZ - 1] = '\\0';\n\n\tdrv->monitor_ifidx =\n\t\tcapwap_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,\n\t\t\t\t     0);\n\n\tif (drv->monitor_ifidx == -EOPNOTSUPP) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Driver does not support \"\n\t\t\t   \"monitor interface type - try to run without it\");\n\t\tdrv->no_monitor_iface_capab = 1;\n\t}\n\n\tif (drv->monitor_ifidx < 0)\n\t\treturn -1;\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))\n\t\tgoto error;\n\n\tmemset(&ll, 0, sizeof(ll));\n\tll.sll_family = AF_PACKET;\n\tll.sll_ifindex = drv->monitor_ifidx;\n\tdrv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n\tif (drv->monitor_sock < 0) {\n\t\tperror(\"socket[PF_PACKET,SOCK_RAW]\");\n\t\tgoto error;\n\t}\n\n\tif (add_monitor_filter(drv->monitor_sock)) {\n\t\twpa_printf(MSG_INFO, \"Failed to set socket filter for monitor \"\n\t\t\t   \"interface; do filtering in user space\");\n\t\t/* This works, but will cost in performance. */\n\t}\n\n\tif (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {\n\t\tperror(\"monitor socket bind\");\n\t\tgoto error;\n\t}\n\n\toptlen = sizeof(optval);\n\toptval = 20;\n\tif (setsockopt\n\t    (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {\n\t\tperror(\"Failed to set socket priority\");\n\t\tgoto error;\n\t}\n\n\n\n\n\n\treturn 0;\n error:\n\tcapwap_remove_monitor_interface(drv);\n\treturn -1;\n}\n\n\n#ifdef CONFIG_AP\nstatic int capwap_send_eapol_data(struct i802_bss *bss,\n\t\t\t\t   const u8 *addr, const u8 *data,\n\t\t\t\t   size_t data_len, const u8 *own_addr)\n{\n\twpa_printf(MSG_DEBUG, \"-------------capwap_send_eapol_data\\n\");\n\tif (bss->drv->l2 == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No l2_packet to send EAPOL\");\n\t\treturn -1;\n\t}\n\n\tif (l2_packet_send(bss->drv->l2, addr, ETH_P_EAPOL, data, data_len) <\n\t    0)\n\t\treturn -1;\n\treturn 0;\n}\n#endif /* CONFIG_AP */\n\n\nstatic const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n\nstatic int wpa_driver_capwap_hapd_send_eapol(\n\tvoid *priv, const u8 *addr, const u8 *data,\n\tsize_t data_len, int encrypt, const u8 *own_addr, u32 flags)\n{\n\n\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct ieee80211_hdr *hdr;\n\tsize_t len;\n\tu8 *pos;\n\tint res;\n\tint qos = flags & WPA_STA_WMM;\nwpa_printf(MSG_DEBUG, \"-------------- wpa_driver_capwap_hapd_send_eapol %d \\n\",bss->ifindex);\n\n#ifdef CONFIG_AP\n\tif (drv->no_monitor_iface_capab)\n\t\treturn capwap_send_eapol_data(bss, addr, data, data_len,\n\t\t\t\t\t       own_addr);\n#endif /* CONFIG_AP */\n\n\tlen = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +\n\t\tdata_len;\n\thdr = os_zalloc(len);\n\tif (hdr == NULL) {\n\t\twpa_printf(MSG_ERROR,\"malloc() failed for i802_send_data(len=%lu)\\n\",\n\t\t       (unsigned long) len);\n\t\treturn -1;\n\t}\n\n\thdr->frame_control =\n\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);\n\thdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);\n\tif (encrypt)\n\t\thdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);\n\tif (qos) {\n\t\thdr->frame_control |=\n\t\t\thost_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);\n\t}\n\n\tmemcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);\n\tmemcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);\n\tmemcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);\n\tpos = (u8 *) (hdr + 1);\n\n\tif (qos) {\n\t\t/* add an empty QoS header if needed */\n\t\tpos[0] = 0;\n\t\tpos[1] = 0;\n\t\tpos += 2;\n\t}\n\n\tmemcpy(pos, rfc1042_header, sizeof(rfc1042_header));\n\tpos += sizeof(rfc1042_header);\n\tWPA_PUT_BE16(pos, ETH_P_PAE);\n\tpos += 2;\n\tmemcpy(pos, data, data_len);\n\twpa_printf(MSG_DEBUG, \"EAPOL Data Frame 1 (%zd)\\n\",len);\n\n\tres = wpa_driver_capwap_send_frame(drv, (u8 *) hdr, len, encrypt);\n\tif (res < 0) {\n\t\twpa_printf(MSG_ERROR, \"i802_send_eapol - packet len: %lu - \"\n\t\t\t   \"failed: %d (%s)\",\n\t\t\t   (unsigned long) len, errno, strerror(errno));\n\t}\n\tos_free(hdr);\n\n\treturn res;\n}\n\n\nstatic int wpa_driver_capwap_sta_set_flags(void *priv, const u8 *addr,\n\t\t\t\t\t    int total_flags,\n\t\t\t\t\t    int flags_or, int flags_and)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg, *flags = NULL;\n\tstruct nl80211_sta_flag_update upd;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tflags = nlmsg_alloc();\n\tif (!flags) {\n\t\tnlmsg_free(msg);\n\t\treturn -ENOMEM;\n\t}\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\n\t/*\n\t * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This\n\t * can be removed eventually.\n\t */\n\tif (total_flags & WPA_STA_AUTHORIZED)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);\n\n\tif (total_flags & WPA_STA_WMM)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);\n\n\tif (total_flags & WPA_STA_SHORT_PREAMBLE)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);\n\n\tif (total_flags & WPA_STA_MFP)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);\n\n\tif (total_flags & WPA_STA_TDLS_PEER)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);\n\n\tif (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))\n\t\tgoto nla_put_failure;\n\n\tos_memset(&upd, 0, sizeof(upd));\n\tupd.mask = sta_flags_capwap(flags_or | ~flags_and);\n\tupd.set = sta_flags_capwap(flags_or);\n\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n\n\tnlmsg_free(flags);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\tnlmsg_free(flags);\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_ap(struct wpa_driver_capwap_data *drv,\n\t\t\t\t struct wpa_driver_associate_params *params)\n{\n\tenum nl80211_iftype nlmode;\n\n\tif (params->p2p) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Setup AP operations for P2P \"\n\t\t\t   \"group (GO)\");\n\t\tnlmode = NL80211_IFTYPE_P2P_GO;\n\t} else\n\t\tnlmode = NL80211_IFTYPE_AP;\n\n\tif (wpa_driver_capwap_set_mode(&drv->first_bss, nlmode) ||\n\t    wpa_driver_capwap_set_freq(drv, params->freq, 0, 0)) {\n\t\tcapwap_remove_monitor_interface(drv);\n\t\treturn -1;\n\t}\n\n\tif (drv->no_monitor_iface_capab) {\n\t\tif (wpa_driver_capwap_probe_req_report(&drv->first_bss, 1) < 0)\n\t\t{\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to enable \"\n\t\t\t\t   \"Probe Request frame reporting in AP mode\");\n\t\t\t/* Try to survive without this */\n\t\t}\n\t}\n\n\tdrv->ap_oper_freq = params->freq;\n\n\treturn 0;\n}\n\n\nstatic int capwap_leave_ibss(struct wpa_driver_capwap_data *drv)\n{\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Leave IBSS failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Leave IBSS request sent successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_ibss(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   struct wpa_driver_associate_params *params)\n{\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\tint count = 0;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS (ifindex=%d)\", drv->ifindex);\n\n\tif (wpa_driver_capwap_set_mode(&drv->first_bss,\n\t\t\t\t\tNL80211_IFTYPE_ADHOC)) {\n\t\twpa_printf(MSG_INFO, \"capwap: Failed to set interface into \"\n\t\t\t   \"IBSS mode\");\n\t\treturn -1;\n\t}\n\nretry:\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tif (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))\n\t\tgoto nla_put_failure;\n\n\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t  params->ssid, params->ssid_len);\n\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n\t\tparams->ssid);\n\tos_memcpy(drv->ssid, params->ssid, params->ssid_len);\n\tdrv->ssid_len = params->ssid_len;\n\n\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\n\tret = capwap_set_conn_keys(params, msg);\n\tif (ret)\n\t\tgoto nla_put_failure;\n\n\tif (params->wpa_ie) {\n\t\twpa_hexdump(MSG_DEBUG,\n\t\t\t    \"  * Extra IEs for Beacon/Probe Response frames\",\n\t\t\t    params->wpa_ie, params->wpa_ie_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n\t\t\tparams->wpa_ie);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS failed: ret=%d (%s)\",\n\t\t\t   ret, strerror(-ret));\n\t\tcount++;\n\t\tif (ret == -EALREADY && count == 1) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Retry IBSS join after \"\n\t\t\t\t   \"forced leave\");\n\t\t\tcapwap_leave_ibss(drv);\n\t\t\tnlmsg_free(msg);\n\t\t\tgoto retry;\n\t\t}\n\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS request sent successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic unsigned int capwap_get_assoc_bssid(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t    u8 *bssid)\n{\n\tstruct nl_msg *msg;\n\tint ret;\n\tstruct capwap_bss_info_arg arg;\n\n\tos_memset(&arg, 0, sizeof(arg));\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\targ.drv = drv;\n\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\tif (is_zero_ether_addr(arg.assoc_bssid))\n\t\t\treturn -ENOTCONN;\n\t\tos_memcpy(bssid, arg.assoc_bssid, ETH_ALEN);\n\t\treturn 0;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n\t\t   \"(%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn drv->assoc_freq;\n}\n\n\nstatic int capwap_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t      const u8 *bssid)\n{\n\tu8 addr[ETH_ALEN];\n\n\tif (bssid == NULL) {\n\t\tint res = capwap_get_assoc_bssid(drv, addr);\n\t\tif (res)\n\t\t\treturn res;\n\t\tbssid = addr;\n\t}\n\n\treturn wpa_driver_capwap_disconnect(drv, bssid,\n\t\t\t\t\t     WLAN_REASON_PREV_AUTH_NOT_VALID);\n}\n\n\nstatic int wpa_driver_capwap_connect(\n\tstruct wpa_driver_capwap_data *drv,\n\tstruct wpa_driver_associate_params *params)\n{\n\tstruct nl_msg *msg;\n\tenum nl80211_auth_type type;\n\tint ret = 0;\n\tint algs;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Connect (ifindex=%d)\", drv->ifindex);\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_CONNECT);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tif (params->bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n\t}\n\tif (params->freq) {\n\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\t}\n\tif (params->ssid) {\n\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t\t  params->ssid, params->ssid_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n\t\t\tparams->ssid);\n\t\tif (params->ssid_len > sizeof(drv->ssid))\n\t\t\tgoto nla_put_failure;\n\t\tos_memcpy(drv->ssid, params->ssid, params->ssid_len);\n\t\tdrv->ssid_len = params->ssid_len;\n\t}\n\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->wpa_ie, params->wpa_ie_len);\n\tif (params->wpa_ie)\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n\t\t\tparams->wpa_ie);\n\n\talgs = 0;\n\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n\t\talgs++;\n\tif (params->auth_alg & WPA_AUTH_ALG_SHARED)\n\t\talgs++;\n\tif (params->auth_alg & WPA_AUTH_ALG_LEAP)\n\t\talgs++;\n\tif (algs > 1) {\n\t\twpa_printf(MSG_DEBUG, \"  * Leave out Auth Type for automatic \"\n\t\t\t   \"selection\");\n\t\tgoto skip_auth_type;\n\t}\n\n\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n\t\ttype = NL80211_AUTHTYPE_OPEN_SYSTEM;\n\telse if (params->auth_alg & WPA_AUTH_ALG_SHARED)\n\t\ttype = NL80211_AUTHTYPE_SHARED_KEY;\n\telse if (params->auth_alg & WPA_AUTH_ALG_LEAP)\n\t\ttype = NL80211_AUTHTYPE_NETWORK_EAP;\n\telse if (params->auth_alg & WPA_AUTH_ALG_FT)\n\t\ttype = NL80211_AUTHTYPE_FT;\n\telse\n\t\tgoto nla_put_failure;\n\n\twpa_printf(MSG_DEBUG, \"  * Auth Type %d\", type);\n\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);\n\nskip_auth_type:\n\tif (params->wpa_proto) {\n\t\tenum nl80211_wpa_versions ver = 0;\n\n\t\tif (params->wpa_proto & WPA_PROTO_WPA)\n\t\t\tver |= NL80211_WPA_VERSION_1;\n\t\tif (params->wpa_proto & WPA_PROTO_RSN)\n\t\t\tver |= NL80211_WPA_VERSION_2;\n\n\t\twpa_printf(MSG_DEBUG, \"  * WPA Versions 0x%x\", ver);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);\n\t}\n\n\tif (params->pairwise_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->pairwise_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);\n\t}\n\n\tif (params->group_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->group_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);\n\t}\n\n\tif (params->key_mgmt_suite == KEY_MGMT_802_1X ||\n\t    params->key_mgmt_suite == KEY_MGMT_PSK) {\n\t\tint mgmt = WLAN_AKM_SUITE_PSK;\n\n\t\tswitch (params->key_mgmt_suite) {\n\t\tcase KEY_MGMT_802_1X:\n\t\t\tmgmt = WLAN_AKM_SUITE_8021X;\n\t\t\tbreak;\n\t\tcase KEY_MGMT_PSK:\n\t\tdefault:\n\t\t\tmgmt = WLAN_AKM_SUITE_PSK;\n\t\t\tbreak;\n\t\t}\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);\n\t}\n\n\tret = capwap_set_conn_keys(params, msg);\n\tif (ret)\n\t\tgoto nla_put_failure;\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME connect failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\t/*\n\t\t * cfg80211 does not currently accept new connection if we are\n\t\t * already connected. As a workaround, force disconnection and\n\t\t * try again once the driver indicates it completed\n\t\t * disconnection.\n\t\t */\n\t\tif (ret == -EALREADY)\n\t\t\tcapwap_disconnect(drv, params->bssid);\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Connect request send successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n\n}\n\n\nstatic int wpa_driver_capwap_associate(\n\tvoid *priv, struct wpa_driver_associate_params *params)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1;\n\tstruct nl_msg *msg;\n\n\tif (params->mode == IEEE80211_MODE_AP)\n\t\treturn wpa_driver_capwap_ap(drv, params);\n\n\tif (params->mode == IEEE80211_MODE_IBSS)\n\t\treturn wpa_driver_capwap_ibss(drv, params);\n\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {\n\t\tenum nl80211_iftype nlmode = params->p2p ?\n\t\t\tNL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;\n\n\t\tif (wpa_driver_capwap_set_mode(priv, nlmode) < 0)\n\t\t\treturn -1;\n\t\treturn wpa_driver_capwap_connect(drv, params);\n\t}\n\n\tdrv->associated = 0;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Associate (ifindex=%d)\",\n\t\t   drv->ifindex);\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tif (params->bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n\t}\n\tif (params->freq) {\n\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\t\tdrv->assoc_freq = params->freq;\n\t} else\n\t\tdrv->assoc_freq = 0;\n\tif (params->ssid) {\n\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t\t  params->ssid, params->ssid_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,\n\t\t\tparams->ssid);\n\t\tif (params->ssid_len > sizeof(drv->ssid))\n\t\t\tgoto nla_put_failure;\n\t\tos_memcpy(drv->ssid, params->ssid, params->ssid_len);\n\t\tdrv->ssid_len = params->ssid_len;\n\t}\n\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->wpa_ie, params->wpa_ie_len);\n\tif (params->wpa_ie)\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n\t\t\tparams->wpa_ie);\n\n\tif (params->pairwise_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->pairwise_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\twpa_printf(MSG_DEBUG, \"  * pairwise=0x%x\", cipher);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);\n\t}\n\n\tif (params->group_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->group_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\twpa_printf(MSG_DEBUG, \"  * group=0x%x\", cipher);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);\n\t}\n\n#ifdef CONFIG_IEEE80211W\n\tif (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);\n#endif /* CONFIG_IEEE80211W */\n\n\tNLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);\n\n\tif (params->prev_bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * prev_bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->prev_bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,\n\t\t\tparams->prev_bssid);\n\t}\n\n\tif (params->p2p)\n\t\twpa_printf(MSG_DEBUG, \"  * P2P group\");\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME command failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tcapwap_dump_scan(drv);\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Association request send \"\n\t\t   \"successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int capwap_set_mode(struct wpa_driver_capwap_data *drv,\n\t\t\t    int ifindex, enum nl80211_iftype mode)\n{\n\n\twpa_printf(MSG_DEBUG, \"#\t\t\t\t\t\t1.wpa_driver_capwap_set_mode\\n\");\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Set mode ifindex %d iftype %d (%s)\",\n\t\t   ifindex, mode, nl80211_iftype_str(mode));\n\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\n\tmsg = NULL;\n\n\tif (!ret)\n\t\treturn 0;\n\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to set interface %d to mode %d:\"\n\t\t   \" %d (%s)\", ifindex, mode, ret, strerror(-ret));\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_set_mode(struct i802_bss *bss,\n\t\t\t\t       enum nl80211_iftype nlmode)\n{\n\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t6.wpa_driver_capwap_set_mode\\n\");\n\t//if(!real)return 0;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1;\n\tint i;\n\tint was_ap = is_ap_interface(drv->nlmode);\n\n\tif (capwap_set_mode(drv, drv->ifindex, nlmode) == 0) {\n\t\tdrv->nlmode = nlmode;\n\t\tret = 0;\n\t\tgoto done;\n\t}\n\n\tif (nlmode == drv->nlmode) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface already in \"\n\t\t\t   \"requested mode - ignore error\");\n\t\tret = 0;\n\t\tgoto done; /* Already in the requested mode */\n\t}\n\n\t/* mac80211 doesn't allow mode changes while the device is up, so\n\t * take the device down, try to set the mode again, and bring the\n\t * device back up.\n\t */\n\twpa_printf(MSG_DEBUG, \"capwap: Try mode change after setting \"\n\t\t   \"interface down\");\n\tfor (i = 0; i < 10; i++) {\n\t\tint res;\n\t\tres = linux_set_iface_flags(drv->global->ioctl_sock,\n\t\t\t\t\t    bss->ifname, 0);\n\t\tif (res == -EACCES || res == -ENODEV)\n\t\t\tbreak;\n\t\tif (res == 0) {\n\t\t\t/* Try to set the mode again while the interface is\n\t\t\t * down */\n\t\t\tret = capwap_set_mode(drv, drv->ifindex, nlmode);\n\t\t\tif (ret == -EACCES)\n\t\t\t\tbreak;\n\t\t\tres = linux_set_iface_flags(drv->global->ioctl_sock,\n\t\t\t\t\t\t    bss->ifname, 1);\n\t\t\tif (res && !ret)\n\t\t\t\tret = -1;\n\t\t\telse if (ret != -EBUSY)\n\t\t\t\tbreak;\n\t\t} else\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to set \"\n\t\t\t\t   \"interface down\");\n\t\tos_sleep(0, 100000);\n\t}\n\n\tif (!ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Mode change succeeded while \"\n\t\t\t   \"interface is down\");\n\t\tdrv->nlmode = nlmode;\n\t\tdrv->ignore_if_down_event = 1;\n\t}\n\ndone:\n\n\tif (!ret && is_ap_interface(nlmode)) {\n\t\t/* Setup additional AP mode functionality if needed */\n\t\tif (!drv->no_monitor_iface_capab && drv->monitor_ifidx < 0 &&\n\t\t    capwap_create_monitor_interface(drv) &&\n\t\t    !drv->no_monitor_iface_capab)\n\t\t\treturn -1;\n\t} else if (!ret && !is_ap_interface(nlmode)) {\n\t\t/* Remove additional AP mode functionality */\n\t\tif (was_ap && drv->no_monitor_iface_capab)\n\t\t\twpa_driver_capwap_probe_req_report(bss, 0);\n\t\tcapwap_remove_monitor_interface(drv);\n\t\tbss->beacon_set = 0;\n\t}\n\n\tif (!ret && is_p2p_interface(drv->nlmode)) {\n\t\tcapwap_disable_11b_rates(drv, drv->ifindex, 1);\n\t\tdrv->disabled_11b_rates = 1;\n\t} else if (!ret && drv->disabled_11b_rates) {\n\t\tcapwap_disable_11b_rates(drv, drv->ifindex, 0);\n\t\tdrv->disabled_11b_rates = 0;\n\t}\n\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface mode change to %d \"\n\t\t\t   \"from %d failed\", nlmode, drv->nlmode);\n\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_get_capa(void *priv,\n\t\t\t\t       struct wpa_driver_capa *capa)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t1.wpa_driver_capwap_get_capa\");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!drv->has_capability)\n\t\treturn -1;\n\tos_memcpy(capa, &drv->capa, sizeof(*capa));\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_set_operstate(void *priv, int state)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\twpa_printf(MSG_DEBUG, \"%s: operstate %d->%d (%s)\",\n\t\t   __func__, drv->operstate, state, state ? \"UP\" : \"DORMANT\");\n\tdrv->operstate = state;\n\treturn netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,\n\t\t\t\t      state ? IF_OPER_UP : IF_OPER_DORMANT);\n}\n\n\nstatic int wpa_driver_capwap_set_supp_port(void *priv, int authorized)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tstruct nl80211_sta_flag_update upd;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);\n\n\tos_memset(&upd, 0, sizeof(upd));\n\tupd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);\n\tif (authorized)\n\t\tupd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);\n\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\n/* Set kernel driver on given frequency (MHz) */\nstatic int i802_set_freq(void *priv, struct hostapd_freq_params *freq)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t1.i802_set_freq\");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\treturn wpa_driver_capwap_set_freq(drv, freq->freq, freq->ht_enabled,\n\t\t\t\t\t   freq->sec_channel_offset);\n}\n\n\n#if defined(HOSTAPD) || defined(CONFIG_AP)\n\nstatic inline int min_int(int a, int b)\n{\n\tif (a < b)\n\t\treturn a;\n\treturn b;\n}\n\n\nstatic int get_key_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\t/*\n\t * TODO: validate the key index and mac address!\n\t * Otherwise, there's a race condition as soon as\n\t * the kernel starts sending key notifications.\n\t */\n\n\tif (tb[NL80211_ATTR_KEY_SEQ])\n\t\tmemcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),\n\t\t       min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));\n\treturn NL_SKIP;\n}\n\n\nstatic int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,\n\t\t\t   int idx, u8 *seq)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);\n\n\tif (addr)\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));\n\n\tmemset(seq, 0, 6);\n\n\treturn send_and_recv_msgs(drv, msg, get_key_handler, seq);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\nint round1=0;\n\nstatic int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates,\n\t\t\t      int mode)\n{\n\twpa_printf(MSG_DEBUG,\"> i802_set_rate_sets\");\n\tif(round1)return 0;\n\telse round1=1;\n\n\tstruct i802_bss *bss = priv;\n\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\tstruct nl_msg *msg;\n\tu8 rates[NL80211_MAX_SUPP_RATES];\n\tu8 rates_len = 0;\n\tint i;\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);\n\n\tfor (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++)\n\t\trates[rates_len++] = basic_rates[i] / 5;\n\n\tNLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\treturn -ENOBUFS;\n}\n\n\nstatic int i802_set_rts(void *priv, int rts)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\tu32 val;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tif (rts >= 2347)\n\t\tval = (u32) -1;\n\telse\n\t\tval = rts;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (!ret)\n\t\treturn 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to set RTS threshold %d: \"\n\t\t   \"%d (%s)\", rts, ret, strerror(-ret));\n\treturn ret;\n}\n\n\nstatic int i802_set_frag(void *priv, int frag)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\tu32 val;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tif (frag >= 2346)\n\t\tval = (u32) -1;\n\telse\n\t\tval = frag;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (!ret)\n\t\treturn 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to set fragmentation threshold \"\n\t\t   \"%d: %d (%s)\", frag, ret, strerror(-ret));\n\treturn ret;\n}\n\n\nstatic int i802_flush(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);\n\n\t/*\n\t * XXX: FIX! this needs to flush all VLANs too\n\t */\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int get_sta_handler(struct nl_msg *msg, void *arg)\n{\n\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct hostap_sta_driver_data *data = arg;\n\tstruct nlattr *stats[NL80211_STA_INFO_MAX + 1];\n\tstatic struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {\n\t\t[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },\n\t};\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\t/*\n\t * TODO: validate the interface and mac address!\n\t * Otherwise, there's a race condition as soon as\n\t * the kernel starts sending station notifications.\n\t */\n\n\tif (!tb[NL80211_ATTR_STA_INFO]) {\n\t\twpa_printf(MSG_DEBUG, \"sta stats missing!\");\n\t\treturn NL_SKIP;\n\t}\n\tif (nla_parse_nested(stats, NL80211_STA_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_STA_INFO],\n\t\t\t     stats_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"failed to parse nested attributes!\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (stats[NL80211_STA_INFO_INACTIVE_TIME])\n\t\tdata->inactive_msec =\n\t\t\tnla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);\n\tif (stats[NL80211_STA_INFO_RX_BYTES])\n\t\tdata->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);\n\tif (stats[NL80211_STA_INFO_TX_BYTES])\n\t\tdata->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);\n\tif (stats[NL80211_STA_INFO_RX_PACKETS])\n\t\tdata->rx_packets =\n\t\t\tnla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);\n\tif (stats[NL80211_STA_INFO_TX_PACKETS])\n\t\tdata->tx_packets =\n\t\t\tnla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);\n\n\treturn NL_SKIP;\n}\n\nstatic int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,\n\t\t\t      const u8 *addr)\n{\n\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tos_memset(data, 0, sizeof(*data));\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);\n\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, get_sta_handler, data);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int i802_set_tx_queue_params(void *priv, int queue, int aifs,\n\t\t\t\t    int cw_min, int cw_max, int burst_time)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tstruct nlattr *txq, *params;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\ttxq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);\n\tif (!txq)\n\t\tgoto nla_put_failure;\n\n\t/* We are only sending parameters for a single TXQ at a time */\n\tparams = nla_nest_start(msg, 1);\n\tif (!params)\n\t\tgoto nla_put_failure;\n\n\tswitch (queue) {\n\tcase 0:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO);\n\t\tbreak;\n\tcase 1:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI);\n\t\tbreak;\n\tcase 2:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE);\n\t\tbreak;\n\tcase 3:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK);\n\t\tbreak;\n\t}\n\t/* Burst time is configured in units of 0.1 msec and TXOP parameter in\n\t * 32 usec, so need to convert the value here. */\n\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32);\n\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);\n\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);\n\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);\n\n\tnla_nest_end(msg, params);\n\n\tnla_nest_end(msg, txq);\n\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n\t\treturn 0;\n\tmsg = NULL;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int i802_set_sta_vlan(void *priv, const u8 *addr,\n\t\t\t     const char *ifname, int vlan_id)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tNLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN,\n\t\t    if_nametoindex(ifname));\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: NL80211_ATTR_STA_VLAN (addr=\"\n\t\t\t   MACSTR \" ifname=%s vlan_id=%d) failed: %d (%s)\",\n\t\t\t   MAC2STR(addr), ifname, vlan_id, ret,\n\t\t\t   strerror(-ret));\n\t}\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int i802_get_inact_sec(void *priv, const u8 *addr)\n{\n\n\tstruct hostap_sta_driver_data data;\n\tint ret;\n\n\tdata.inactive_msec = (unsigned long) -1;\n\tret = i802_read_sta_data(priv, &data, addr);\n\tif (ret || data.inactive_msec == (unsigned long) -1)\n\t\treturn -1;\n\treturn data.inactive_msec / 1000;\n}\n\n\nstatic int i802_sta_clear_stats(void *priv, const u8 *addr)\n{\n#if 0\n\t/* TODO */\n#endif\n\treturn 0;\n}\n\n\nstatic int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,\n\t\t\t   int reason)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t\t\t\t\t1.i802_sta_deauth\");\n\n\tstruct i802_bss *bss = priv;\n\tstruct ieee80211_mgmt mgmt;\n\n\tmemset(&mgmt, 0, sizeof(mgmt));\n\tmgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,\n\t\t\t\t\t  WLAN_FC_STYPE_DEAUTH);\n\tmemcpy(mgmt.da, addr, ETH_ALEN);\n\tmemcpy(mgmt.sa, own_addr, ETH_ALEN);\n\tmemcpy(mgmt.bssid, own_addr, ETH_ALEN);\n\tmgmt.u.deauth.reason_code = host_to_le16(reason);\n\tint r = wpa_driver_capwap_send_mlme(bss, (u8 *) &mgmt,\n\t\t\t\t\t    IEEE80211_HDRLEN +\n\t\t\t\t\t    sizeof(mgmt.u.deauth));\n\n\treturn r;\n}\n\n\nstatic int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,\n\t\t\t     int reason)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct ieee80211_mgmt mgmt;\n\n\tmemset(&mgmt, 0, sizeof(mgmt));\n\tmgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,\n\t\t\t\t\t  WLAN_FC_STYPE_DISASSOC);\n\tmemcpy(mgmt.da, addr, ETH_ALEN);\n\tmemcpy(mgmt.sa, own_addr, ETH_ALEN);\n\tmemcpy(mgmt.bssid, own_addr, ETH_ALEN);\n\tmgmt.u.disassoc.reason_code = host_to_le16(reason);\n\treturn wpa_driver_capwap_send_mlme(bss, (u8 *) &mgmt,\n\t\t\t\t\t    IEEE80211_HDRLEN +\n\t\t\t\t\t    sizeof(mgmt.u.disassoc));\n}\n\n#endif /* HOSTAPD || CONFIG_AP */\n\n#ifdef HOSTAPD\n\nstatic void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t3.add_ifidx\");\n\tint i;\n\tint *old;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Add own interface ifindex %d\",\n\t\t   ifidx);\n\tfor (i = 0; i < drv->num_if_indices; i++) {\n\t\tif (drv->if_indices[i] == 0) {\n\t\t\tdrv->if_indices[i] = ifidx;\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (drv->if_indices != drv->default_if_indices)\n\t\told = drv->if_indices;\n\telse\n\t\told = NULL;\n\n\tdrv->if_indices = os_realloc(old,\n\t\t\t\t     sizeof(int) * (drv->num_if_indices + 1));\n\tif (!drv->if_indices) {\n\t\tif (!old)\n\t\t\tdrv->if_indices = drv->default_if_indices;\n\t\telse\n\t\t\tdrv->if_indices = old;\n\t\twpa_printf(MSG_ERROR, \"Failed to reallocate memory for \"\n\t\t\t   \"interfaces\");\n\t\twpa_printf(MSG_ERROR, \"Ignoring EAPOL on interface %d\", ifidx);\n\t\treturn;\n\t} else if (!old)\n\t\tos_memcpy(drv->if_indices, drv->default_if_indices,\n\t\t\t  sizeof(drv->default_if_indices));\n\tdrv->if_indices[drv->num_if_indices] = ifidx;\n\tdrv->num_if_indices++;\n}\n\n\nstatic void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n\tint i;\n\n\tfor (i = 0; i < drv->num_if_indices; i++) {\n\t\tif (drv->if_indices[i] == ifidx) {\n\t\t\tdrv->if_indices[i] = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\nstatic int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n\tint i;\n\n\tfor (i = 0; i < drv->num_if_indices; i++)\n\t\tif (drv->if_indices[i] == ifidx)\n\t\t\treturn 1;\n\n\treturn 0;\n}\n\n\nstatic int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,\n                            const char *bridge_ifname)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tchar name[IFNAMSIZ + 1];\n\n\tos_snprintf(name, sizeof(name), \"%s.sta%d\", bss->ifname, aid);\n\twpa_printf(MSG_DEBUG, \"capwap: Set WDS STA addr=\" MACSTR\n\t\t   \" aid=%d val=%d name=%s\", MAC2STR(addr), aid, val, name);\n\tif (val) {\n\t\tif (!if_nametoindex(name)) {\n\t\t\tif (capwap_create_iface(drv, name,\n\t\t\t\t\t\t NL80211_IFTYPE_AP_VLAN,\n\t\t\t\t\t\t NULL, 1) < 0)\n\t\t\t\treturn -1;\n\t\t\tif (bridge_ifname &&\n\t\t\t    linux_br_add_if(drv->global->ioctl_sock,\n\t\t\t\t\t    bridge_ifname, name) < 0)\n\t\t\t\treturn -1;\n\t\t}\n\t\tlinux_set_iface_flags(drv->global->ioctl_sock, name, 1);\n\t\treturn i802_set_sta_vlan(priv, addr, name, 0);\n\t} else {\n\t\ti802_set_sta_vlan(priv, addr, bss->ifname, 0);\n\t\treturn wpa_driver_capwap_if_remove(priv, WPA_IF_AP_VLAN,\n\t\t\t\t\t\t    name);\n\t}\n}\n\nvoid AC_handle_eapol(struct wpa_driver_capwap_data *drv, u8 *buf, int len){\n\tu8 sa[6];\n\n\tint hlen = GetEapol_Frame(sa, buf, len);\n\t//stampa_mac(\"AC eapol: \" ,sa);\n\n\tdrv_event_eapol_rx(drv->ctx, sa, buf + hlen, len - hlen);\n}\n\n\nstatic void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)\n{\n\n\twpa_printf(MSG_DEBUG, \"handle_eapol %d\\n\",sock);\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\tstruct sockaddr_ll lladdr;\n\tunsigned char buf[3000];\n\tint len;\n\tsocklen_t fromlen = sizeof(lladdr);\n\n\tlen = recvfrom(sock, buf, sizeof(buf), 0,\n\t\t       (struct sockaddr *)&lladdr, &fromlen);\n\n\treturn;\n\tif (len < 0) {\n\t\twpa_printf(MSG_ERROR, \"recv\");\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"LOCALE\");\n\t//stampa_frame(buf,len);\n\n\twpa_printf(MSG_DEBUG, \"%d,%d\", len,have_ifidx(drv, lladdr.sll_ifindex));\n\n\t//stampa_mac(\"  EAPOL MAC: \",lladdr.sll_addr);\n\n\tdrv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);\n}\n\n\nstatic int i802_check_bridge(struct wpa_driver_capwap_data *drv,\n\t\t\t     struct i802_bss *bss,\n\t\t\t     const char *brname, const char *ifname)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t7.i802_check_bridge\");\n\tint ifindex;\n\tchar in_br[IFNAMSIZ];\n\n\tos_strlcpy(bss->brname, brname, IFNAMSIZ);\n\tifindex = if_nametoindex(brname);\n\tif (ifindex == 0) {\n\t\t/*\n\t\t * Bridge was configured, but the bridge device does\n\t\t * not exist. Try to add it now.\n\t\t */\n\t\tif (linux_br_add(drv->global->ioctl_sock, brname) < 0) {\n\t\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add the \"\n\t\t\t\t   \"bridge interface %s: %s\",\n\t\t\t\t   brname, strerror(errno));\n\t\t\treturn -1;\n\t\t}\n\t\tbss->added_bridge = 1;\n\t\tadd_ifidx(drv, if_nametoindex(brname));\n\t}\n\n\tif (linux_br_get(in_br, ifname) == 0) {\n\t\tif (os_strcmp(in_br, brname) == 0)\n\t\t\treturn 0; /* already in the bridge */\n\n\t\twpa_printf(MSG_DEBUG, \"capwap: Removing interface %s from \"\n\t\t\t   \"bridge %s\", ifname, in_br);\n\t\tif (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <\n\t\t    0) {\n\t\t\twpa_printf(MSG_ERROR, \"capwap: Failed to \"\n\t\t\t\t   \"remove interface %s from bridge \"\n\t\t\t\t   \"%s: %s\",\n\t\t\t\t   ifname, brname, strerror(errno));\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Adding interface %s into bridge %s\",\n\t\t   ifname, brname);\n\tif (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add interface %s \"\n\t\t\t   \"into bridge %s: %s\",\n\t\t\t   ifname, brname, strerror(errno));\n\t\treturn -1;\n\t}\n\tbss->added_if_into_bridge = 1;\n\n\treturn 0;\n}\n\n\nstatic void *i802_init(struct hostapd_data *hapd,\n\t\t       struct wpa_init_params *params)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t1.i802_init\");\n\n\n\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct i802_bss *bss;\n\tsize_t i;\n\tchar brname[IFNAMSIZ];\n\tint ifindex, br_ifindex;\n\tint br_added = 0;\n\n\tbss = wpa_driver_capwap_init(hapd, params->ifname,\n\t\t\t\t      params->global_priv);\n\n\tif (bss == NULL)\n\t\treturn NULL;\n\n\tdrv = bss->drv;\n\n\tdrv->nlmode = NL80211_IFTYPE_AP;\n\tdrv->eapol_sock = -1;\n\n\tbrname[0] = 0;\n\tif (linux_br_get(brname, params->ifname) == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface %s is in bridge %s\",\n\t\t\t   params->ifname, brname);\n\t\tbr_ifindex = if_nametoindex(brname);\n\t} else {\n\t\tbrname[0] = '\\0';\n\t\tbr_ifindex = 0;\n\t}\n\n\tdrv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);\n\tdrv->if_indices = drv->default_if_indices;\n\tfor (i = 0; i < params->num_bridge; i++) {\n\t\tif (params->bridge[i]) {\n\t\t\tifindex = if_nametoindex(params->bridge[i]);\n\t\t\tif (ifindex)\n\t\t\t\tadd_ifidx(drv, ifindex);\n\t\t\tif (ifindex == br_ifindex)\n\t\t\t\tbr_added = 1;\n\t\t}\n\t}\n\n\tif (!br_added && br_ifindex &&\n\t    (params->num_bridge == 0 || !params->bridge[0]))\n\t\tadd_ifidx(drv, br_ifindex);\n\n\t/* start listening for EAPOL on the default AP interface */\n\tadd_ifidx(drv, drv->ifindex);\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0))\n\t\tgoto failed;\n\n\tif (params->bssid) {\n\t\tif (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t\t       params->bssid))\n\t\t\tgoto failed;\n\t}\n\n\t//if (eloop_register_read_sock(sockfd, AC_handle_recv_data_from_WTP,drv, NULL)) {\n\t//\t\twpa_printf(MSG_ERROR,\"Could not register UDP server socket\");\n\t//\t\tgoto failed;\n\t//}\n\n\tif (wpa_driver_capwap_set_mode(bss, drv->nlmode)) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to set interface %s \"\n\t\t\t   \"into AP mode\", bss->ifname);\n\t\tgoto failed;\n\t}\n\n\n\tif (params->num_bridge && params->bridge[0] &&\n\t    i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)\n\t\tgoto failed;\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1))\n\t\tgoto failed;\n\n\tdrv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));\n\tif (drv->eapol_sock < 0) {\n\t\tperror(\"socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)\");\n\t\tgoto failed;\n\t}\n\n\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,  params->own_addr))\n\t\tgoto failed;\n\n\tgeneric_ac_info.pseudo_interface = params->ifname;\n\n\tgeneric_ac_info.fd_ipc = start_ipc(drv->ctx, AC_inject_frame_in_hostapd);\n\n\tcapability_get_mac(generic_ac_info.own_mac_addr);\n\tmemcpy(drv->addr,generic_ac_info.own_mac_addr, ETH_ALEN);\n\tmemcpy(params->own_addr,generic_ac_info.own_mac_addr, ETH_ALEN);\n\n\tif(generic_ac_info.fd_ipc<=0){\n\t\twpa_printf(MSG_ERROR, \"Error: start_ipc\");\n\t\treturn NULL;\n\t}\n\n\treturn bss;\n\nfailed:\n\twpa_driver_capwap_deinit(bss);\n\treturn NULL;\n}\n\n\nstatic void i802_deinit(void *priv)\n{\n\tipc_send_DEL_WLAN(generic_ac_info.fd_ipc);\n\tend_ipc(generic_ac_info.fd_ipc);\n\n\twpa_driver_capwap_deinit(priv);\n}\n\n#endif /* HOSTAPD */\n\n\nstatic enum nl80211_iftype wpa_driver_capwap_if_type(\n\tenum wpa_driver_if_type type)\n{\n\tswitch (type) {\n\tcase WPA_IF_STATION:\n\t\treturn NL80211_IFTYPE_STATION;\n\tcase WPA_IF_P2P_CLIENT:\n\tcase WPA_IF_P2P_GROUP:\n\t\treturn NL80211_IFTYPE_P2P_CLIENT;\n\tcase WPA_IF_AP_VLAN:\n\t\treturn NL80211_IFTYPE_AP_VLAN;\n\tcase WPA_IF_AP_BSS:\n\t\treturn NL80211_IFTYPE_AP;\n\tcase WPA_IF_P2P_GO:\n\t\treturn NL80211_IFTYPE_P2P_GO;\n\t}\n\treturn -1;\n}\n\n\n#ifdef CONFIG_P2P\n\nstatic int capwap_addr_in_use(struct capwap_global *global, const u8 *addr)\n{\n\tstruct wpa_driver_capwap_data *drv;\n\tdl_list_for_each(drv, &global->interfaces,\n\t\t\t struct wpa_driver_capwap_data, list) {\n\t\tif (os_memcmp(addr, drv->addr, ETH_ALEN) == 0)\n\t\t\treturn 1;\n\t}\n\treturn 0;\n}\n\n\nstatic int capwap_p2p_interface_addr(struct wpa_driver_capwap_data *drv,\n\t\t\t\t      u8 *new_addr)\n{\n\tunsigned int idx;\n\n\tif (!drv->global)\n\t\treturn -1;\n\n\tos_memcpy(new_addr, drv->addr, ETH_ALEN);\n\tfor (idx = 0; idx < 64; idx++) {\n\t\tnew_addr[0] = drv->addr[0] | 0x02;\n\t\tnew_addr[0] ^= idx << 2;\n\t\tif (!capwap_addr_in_use(drv->global, new_addr))\n\t\t\tbreak;\n\t}\n\tif (idx == 64)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Assigned new P2P Interface Address \"\n\t\t   MACSTR, MAC2STR(new_addr));\n\n\treturn 0;\n}\n\n#endif /* CONFIG_P2P */\n\n\nstatic int wpa_driver_capwap_if_add(void *priv, enum wpa_driver_if_type type,\n\t\t\t\t     const char *ifname, const u8 *addr,\n\t\t\t\t     void *bss_ctx, void **drv_priv,\n\t\t\t\t     char *force_ifname, u8 *if_addr,\n\t\t\t\t     const char *bridge)\n{\n\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ifidx;\n#ifdef HOSTAPD\n\tstruct i802_bss *new_bss = NULL;\n\n\tif (type == WPA_IF_AP_BSS) {\n\t\tnew_bss = os_zalloc(sizeof(*new_bss));\n\t\tif (new_bss == NULL)\n\t\t\treturn -1;\n\t}\n#endif /* HOSTAPD */\n\n\tif (addr)\n\t\tos_memcpy(if_addr, addr, ETH_ALEN);\n\tifidx = capwap_create_iface(drv, ifname,\n\t\t\t\t     wpa_driver_capwap_if_type(type), addr,\n\t\t\t\t     0);\n\tif (ifidx < 0) {\n#ifdef HOSTAPD\n\t\tos_free(new_bss);\n#endif /* HOSTAPD */\n\t\treturn -1;\n\t}\n\n\tif (!addr &&\n\t    linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t       if_addr) < 0) {\n\t\tcapwap_remove_iface(drv, ifidx);\n\t\treturn -1;\n\t}\n\n#ifdef CONFIG_P2P\n\tif (!addr &&\n\t    (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||\n\t     type == WPA_IF_P2P_GO)) {\n\t\t/* Enforce unique P2P Interface Address */\n\t\tu8 new_addr[ETH_ALEN], own_addr[ETH_ALEN];\n\n\t\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t\t       own_addr) < 0 ||\n\t\t    linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,\n\t\t\t\t       new_addr) < 0) {\n\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\treturn -1;\n\t\t}\n\t\tif (os_memcmp(own_addr, new_addr, ETH_ALEN) == 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Allocate new address \"\n\t\t\t\t   \"for P2P group interface\");\n\t\t\tif (capwap_p2p_interface_addr(drv, new_addr) < 0) {\n\t\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,\n\t\t\t\t\t       new_addr) < 0) {\n\t\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t\tos_memcpy(if_addr, new_addr, ETH_ALEN);\n\t}\n#endif /* CONFIG_P2P */\n\n#ifdef HOSTAPD\n\tif (bridge &&\n\t    i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add the new \"\n\t\t\t   \"interface %s to a bridge %s\", ifname, bridge);\n\t\tcapwap_remove_iface(drv, ifidx);\n\t\tos_free(new_bss);\n\t\treturn -1;\n\t}\n\n\tif (type == WPA_IF_AP_BSS) {\n\t\tif (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))\n\t\t{\n\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\tos_free(new_bss);\n\t\t\treturn -1;\n\t\t}\n\t\tos_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);\n\t\tnew_bss->ifindex = ifidx;\n\t\tnew_bss->drv = drv;\n\t\tnew_bss->next = drv->first_bss.next;\n\t\tdrv->first_bss.next = new_bss;\n\t\tif (drv_priv)\n\t\t\t*drv_priv = new_bss;\n\t}\n#endif /* HOSTAPD */\n\n\tif (drv->global)\n\t\tdrv->global->if_add_ifindex = ifidx;\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_if_remove(void *priv,\n\t\t\t\t\tenum wpa_driver_if_type type,\n\t\t\t\t\tconst char *ifname)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ifindex = if_nametoindex(ifname);\n\n\twpa_printf(MSG_DEBUG, \"capwap: %s(type=%d ifname=%s) ifindex=%d\",\n\t\t   __func__, type, ifname, ifindex);\n\tif (ifindex <= 0)\n\t\treturn -1;\n\n#ifdef HOSTAPD\n\tif (bss->added_if_into_bridge) {\n\t\tif (linux_br_del_if(drv->global->ioctl_sock, bss->brname,\n\t\t\t\t    bss->ifname) < 0)\n\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n\t\t\t\t   \"interface %s from bridge %s: %s\",\n\t\t\t\t   bss->ifname, bss->brname, strerror(errno));\n\t}\n\tif (bss->added_bridge) {\n\t\tif (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)\n\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n\t\t\t\t   \"bridge %s: %s\",\n\t\t\t\t   bss->brname, strerror(errno));\n\t}\n#endif /* HOSTAPD */\n\n\tcapwap_remove_iface(drv, ifindex);\n\n#ifdef HOSTAPD\n\tif (type != WPA_IF_AP_BSS)\n\t\treturn 0;\n\n\tif (bss != &drv->first_bss) {\n\t\tstruct i802_bss *tbss;\n\n\t\tfor (tbss = &drv->first_bss; tbss; tbss = tbss->next) {\n\t\t\tif (tbss->next == bss) {\n\t\t\t\ttbss->next = bss->next;\n\t\t\t\tos_free(bss);\n\t\t\t\tbss = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (bss)\n\t\t\twpa_printf(MSG_INFO, \"capwap: %s - could not find \"\n\t\t\t\t   \"BSS %p in the list\", __func__, bss);\n\t}\n#endif /* HOSTAPD */\n\n\treturn 0;\n}\n\n\nstatic int cookie_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tu64 *cookie = arg;\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (tb[NL80211_ATTR_COOKIE])\n\t\t*cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_send_frame_cmd(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  unsigned int freq, unsigned int wait,\n\t\t\t\t  const u8 *buf, size_t buf_len,\n\t\t\t\t  u64 *cookie_out, int no_cck)\n{\n\tstruct nl_msg *msg;\n\tu64 cookie;\n\tint ret = -1;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_FRAME);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);\n\tif (wait)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);\n\tNLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);\n\tif (no_cck)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);\n\n\tNLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);\n\n\tcookie = 0;\n\tret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Frame command failed: ret=%d \"\n\t\t\t   \"(%s) (freq=%u wait=%u)\", ret, strerror(-ret),\n\t\t\t   freq, wait);\n\t\tgoto nla_put_failure;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Frame TX command accepted; \"\n\t\t   \"cookie 0x%llx\", (long long unsigned int) cookie);\n\n\tif (cookie_out)\n\t\t*cookie_out = cookie;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_send_action(void *priv, unsigned int freq,\n\t\t\t\t\t  unsigned int wait_time,\n\t\t\t\t\t  const u8 *dst, const u8 *src,\n\t\t\t\t\t  const u8 *bssid,\n\t\t\t\t\t  const u8 *data, size_t data_len,\n\t\t\t\t\t  int no_cck)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1;\n\tu8 *buf;\n\tstruct ieee80211_hdr *hdr;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Send Action frame (ifindex=%d, \"\n\t\t   \"wait=%d ms no_cck=%d)\", drv->ifindex, wait_time, no_cck);\n\n\tbuf = os_zalloc(24 + data_len);\n\tif (buf == NULL)\n\t\treturn ret;\n\tos_memcpy(buf + 24, data, data_len);\n\thdr = (struct ieee80211_hdr *) buf;\n\thdr->frame_control =\n\t\tIEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);\n\tos_memcpy(hdr->addr1, dst, ETH_ALEN);\n\tos_memcpy(hdr->addr2, src, ETH_ALEN);\n\tos_memcpy(hdr->addr3, bssid, ETH_ALEN);\n\n\tif (is_ap_interface(drv->nlmode))\n\t\tret = wpa_driver_capwap_send_mlme(priv, buf, 24 + data_len);\n\telse\n\t\tret = capwap_send_frame_cmd(drv, freq, wait_time, buf,\n\t\t\t\t\t     24 + data_len,\n\t\t\t\t\t     &drv->send_action_cookie,\n\t\t\t\t\t     no_cck);\n\n\tos_free(buf);\n\treturn ret;\n}\n\n\nstatic void wpa_driver_capwap_send_action_cancel_wait(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: wait cancel failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\n nla_put_failure:\n\tnlmsg_free(msg);\n}\n\n\nstatic int wpa_driver_capwap_remain_on_channel(void *priv, unsigned int freq,\n\t\t\t\t\t\tunsigned int duration)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\tu64 cookie;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);\n\tNLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);\n\n\tcookie = 0;\n\tret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Remain-on-channel cookie \"\n\t\t\t   \"0x%llx for freq=%u MHz duration=%u\",\n\t\t\t   (long long unsigned int) cookie, freq, duration);\n\t\tdrv->remain_on_chan_cookie = cookie;\n\t\tdrv->pending_remain_on_chan = 1;\n\t\treturn 0;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to request remain-on-channel \"\n\t\t   \"(freq=%d duration=%u): %d (%s)\",\n\t\t   freq, duration, ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int wpa_driver_capwap_cancel_remain_on_channel(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\n\tif (!drv->pending_remain_on_chan) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No pending remain-on-channel \"\n\t\t\t   \"to cancel\");\n\t\treturn -1;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Cancel remain-on-channel with cookie \"\n\t\t   \"0x%llx\",\n\t\t   (long long unsigned int) drv->remain_on_chan_cookie);\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret == 0)\n\t\treturn 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to cancel remain-on-channel: \"\n\t\t   \"%d (%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int wpa_driver_capwap_probe_req_report(void *priv, int report)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\tif (!report) {\n\t\tif (drv->nl_preq.handle && drv->no_monitor_iface_capab &&\n\t\t    is_ap_interface(drv->nlmode)) {\n\t\t\t/*\n\t\t\t * Do not disable Probe Request reporting that was\n\t\t\t * enabled in capwap_setup_ap().\n\t\t\t */\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Skip disabling of \"\n\t\t\t\t   \"Probe Request reporting nl_preq=%p while \"\n\t\t\t\t   \"in AP mode\", drv->nl_preq.handle);\n\t\t} else if (drv->nl_preq.handle) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Disable Probe Request \"\n\t\t\t\t   \"reporting nl_preq=%p\", drv->nl_preq.handle);\n\t\t\teloop_unregister_read_sock(\n\t\t\t\tnl_socket_get_fd(drv->nl_preq.handle));\n\t\t\tnl_destroy_handles(&drv->nl_preq);\n\t\t}\n\t\treturn 0;\n\t}\n\n\tif (drv->nl_preq.handle) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Probe Request reporting \"\n\t\t\t   \"already on!\");\n\t\treturn 0;\n\t}\n\n\tif (nl_create_handles(&drv->nl_preq, drv->global->nl_cb, \"preq\"))\n\t\treturn -1;\n\n\tif (capwap_register_frame(drv, drv->nl_preq.handle,\n\t\t\t\t   (WLAN_FC_TYPE_MGMT << 2) |\n\t\t\t\t   (WLAN_FC_STYPE_PROBE_REQ << 4),\n\t\t\t\t   NULL, 0) < 0)\n\t\tgoto out_err;\n\n\teloop_register_read_sock(nl_socket_get_fd(drv->nl_preq.handle),\n\t\t\t\t wpa_driver_capwap_event_receive, drv,\n\t\t\t\t drv->nl_preq.handle);\n\n\treturn 0;\n\n out_err:\n\tnl_destroy_handles(&drv->nl_preq);\n\treturn -1;\n}\n\n\nstatic int capwap_disable_11b_rates(struct wpa_driver_capwap_data *drv,\n\t\t\t\t     int ifindex, int disabled)\n{\n\tstruct nl_msg *msg;\n\tstruct nlattr *bands, *band;\n\tint ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\n\tbands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);\n\tif (!bands)\n\t\tgoto nla_put_failure;\n\n\t/*\n\t * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything\n\t * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS\n\t * rates. All 5 GHz rates are left enabled.\n\t */\n\tband = nla_nest_start(msg, NL80211_BAND_2GHZ);\n\tif (!band)\n\t\tgoto nla_put_failure;\n\tif (disabled) {\n\t\tNLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,\n\t\t\t\"\\x0c\\x12\\x18\\x24\\x30\\x48\\x60\\x6c\");\n\t}\n\tnla_nest_end(msg, band);\n\n\tnla_nest_end(msg, bands);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Set TX rates failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t}\n\n\treturn ret;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int wpa_driver_capwap_deinit_ap(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!is_ap_interface(drv->nlmode))\n\t\treturn -1;\n\twpa_driver_capwap_del_beacon(drv);\n\treturn wpa_driver_capwap_set_mode(priv, NL80211_IFTYPE_STATION);\n}\n\n\nstatic int wpa_driver_capwap_deinit_p2p_cli(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)\n\t\treturn -1;\n\treturn wpa_driver_capwap_set_mode(priv, NL80211_IFTYPE_STATION);\n}\n\n\nstatic void wpa_driver_capwap_resume(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to set interface up on \"\n\t\t\t   \"resume event\");\n\t}\n}\n\n\nstatic int capwap_send_ft_action(void *priv, u8 action, const u8 *target_ap,\n\t\t\t\t  const u8 *ies, size_t ies_len)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret;\n\tu8 *data, *pos;\n\tsize_t data_len;\n\tu8 own_addr[ETH_ALEN];\n\n\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t       own_addr) < 0)\n\t\treturn -1;\n\n\tif (action != 1) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Unsupported send_ft_action \"\n\t\t\t   \"action %d\", action);\n\t\treturn -1;\n\t}\n\n\t/*\n\t * Action frame payload:\n\t * Category[1] = 6 (Fast BSS Transition)\n\t * Action[1] = 1 (Fast BSS Transition Request)\n\t * STA Address\n\t * Target AP Address\n\t * FT IEs\n\t */\n\n\tdata_len = 2 + 2 * ETH_ALEN + ies_len;\n\tdata = os_malloc(data_len);\n\tif (data == NULL)\n\t\treturn -1;\n\tpos = data;\n\t*pos++ = 0x06; /* FT Action category */\n\t*pos++ = action;\n\tos_memcpy(pos, own_addr, ETH_ALEN);\n\tpos += ETH_ALEN;\n\tos_memcpy(pos, target_ap, ETH_ALEN);\n\tpos += ETH_ALEN;\n\tos_memcpy(pos, ies, ies_len);\n\n\tret = wpa_driver_capwap_send_action(bss, drv->assoc_freq, 0,\n\t\t\t\t\t     drv->bssid, own_addr, drv->bssid,\n\t\t\t\t\t     data, data_len, 0);\n\tos_free(data);\n\n\treturn ret;\n}\n\n\nstatic int capwap_signal_monitor(void *priv, int threshold, int hysteresis)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg, *cqm = NULL;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Signal monitor threshold=%d \"\n\t\t   \"hysteresis=%d\", threshold, hysteresis);\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n\n\tcqm = nlmsg_alloc();\n\tif (cqm == NULL)\n\t\treturn -1;\n\n\tNLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold);\n\tNLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);\n\tnla_put_nested(msg, NL80211_ATTR_CQM, cqm);\n\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n\t\treturn 0;\n\tmsg = NULL;\n\nnla_put_failure:\n\tnlmsg_free(cqm);\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int capwap_signal_poll(void *priv, struct wpa_signal_info *si)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint res;\n\n\tos_memset(si, 0, sizeof(*si));\n\tres = capwap_get_link_signal(drv, si);\n\tif (res != 0)\n\t\treturn res;\n\n\treturn capwap_get_link_noise(drv, si);\n}\n\n\nstatic int capwap_send_frame(void *priv, const u8 *data, size_t data_len,\n\t\t\t      int encrypt)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\treturn wpa_driver_capwap_send_frame(drv, data, data_len, encrypt);\n}\n\n\nstatic int capwap_set_param(void *priv, const char *param)\n{\n\n\twpa_printf(MSG_DEBUG, \"capwap: driver param='%s'\", param);\n\tif (param == NULL)\n\t\treturn 0;\n\n#ifdef CONFIG_P2P\n\tif (os_strstr(param, \"use_p2p_group_interface=1\")) {\n\t\tstruct i802_bss *bss = priv;\n\t\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\t\twpa_printf(MSG_DEBUG, \"capwap: Use separate P2P group \"\n\t\t\t   \"interface\");\n\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;\n\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;\n\t}\n#endif /* CONFIG_P2P */\n\n\treturn 0;\n}\n\n\nstatic void * capwap_global_init(void)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t1.capwap_global_init\");\n\tstruct capwap_global *global;\n\tstruct netlink_config *cfg;\n\n\tglobal = os_zalloc(sizeof(*global));\n\tif (global == NULL)\n\t\treturn NULL;\n\tglobal->ioctl_sock = -1;\n\tdl_list_init(&global->interfaces);\n\tglobal->if_add_ifindex = -1;\n\n\tcfg = os_zalloc(sizeof(*cfg));\n\tif (cfg == NULL)\n\t\tgoto err;\n\tcfg->ctx = global;\n\tcfg->newlink_cb = wpa_driver_capwap_event_rtm_newlink;\n\tcfg->dellink_cb = wpa_driver_capwap_event_rtm_dellink;\n\tglobal->netlink = netlink_init(cfg);\n\tif (global->netlink == NULL) {\n\t\tos_free(cfg);\n\t\tgoto err;\n\t}\n\tif (wpa_driver_capwap_init_nl_global(global) < 0)\n\t\tgoto err;\n\tglobal->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);\n\tif (global->ioctl_sock < 0) {\n\t\tperror(\"socket(PF_INET,SOCK_DGRAM)\");\n\t\tgoto err;\n\t}\n\n\treturn global;\n\nerr:\n\tcapwap_global_deinit(global);\n\treturn NULL;\n}\n\n\nstatic void capwap_global_deinit(void *priv)\n{\n\n\tstruct capwap_global *global = priv;\n\tif (global == NULL)\n\t\treturn;\n\tif (!dl_list_empty(&global->interfaces)) {\n\t\twpa_printf(MSG_ERROR, \"capwap: %u interface(s) remain at \"\n\t\t\t   \"capwap_global_deinit\",\n\t\t\t   dl_list_len(&global->interfaces));\n\t}\n\n\tif (global->netlink)\n\t\tnetlink_deinit(global->netlink);\n\n\tif (global->capwap)\n\t\tgenl_family_put(global->capwap);\n\tnl_destroy_handles(&global->nl);\n\n\tif (global->nl_cb)\n\t\tnl_cb_put(global->nl_cb);\n\n\tif (global->ioctl_sock >= 0)\n\t\tclose(global->ioctl_sock);\n\n\tos_free(global);\n}\n\n\nstatic const char * capwap_get_radio_name(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\treturn drv->phyname;\n}\n\n\nstatic int capwap_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,\n\t\t\t const u8 *pmkid)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(bss->drv, msg, 0, cmd);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\tif (pmkid)\n\t\tNLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid);\n\tif (bssid)\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);\n\n\treturn send_and_recv_msgs(bss->drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int capwap_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)\n{\n\n\tstruct i802_bss *bss = priv;\n\twpa_printf(MSG_DEBUG, \"capwap: Add PMKID for \" MACSTR, MAC2STR(bssid));\n\treturn capwap_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);\n}\n\n\nstatic int capwap_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)\n{\n\n\tstruct i802_bss *bss = priv;\n\twpa_printf(MSG_DEBUG, \"capwap: Delete PMKID for \" MACSTR,\n\t\t   MAC2STR(bssid));\n\treturn capwap_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);\n}\n\n\nstatic int capwap_flush_pmkid(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\twpa_printf(MSG_DEBUG, \"capwap: Flush PMKIDs\");\n\treturn capwap_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);\n}\n\n\nstatic void capwap_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,\n\t\t\t\t   const u8 *replay_ctr)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nlattr *replay_nested;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n\n\treplay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);\n\tif (!replay_nested)\n\t\tgoto nla_put_failure;\n\n\tNLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);\n\tNLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);\n\tNLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,\n\t\treplay_ctr);\n\n\tnla_nest_end(msg, replay_nested);\n\n\tsend_and_recv_msgs(drv, msg, NULL, NULL);\n\treturn;\n nla_put_failure:\n\tnlmsg_free(msg);\n}\n\n\nstatic void capwap_poll_client(void *priv, const u8 *own_addr, const u8 *addr,\n\t\t\t\tint qos)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct {\n\t\tstruct ieee80211_hdr hdr;\n\t\tu16 qos_ctl;\n\t} STRUCT_PACKED nulldata;\n\tsize_t size;\n\n\t/* Send data frame to poll STA and check whether this frame is ACKed */\n\n\tos_memset(&nulldata, 0, sizeof(nulldata));\n\n\tif (qos) {\n\t\tnulldata.hdr.frame_control =\n\t\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA,\n\t\t\t\t     WLAN_FC_STYPE_QOS_NULL);\n\t\tsize = sizeof(nulldata);\n\t} else {\n\t\tnulldata.hdr.frame_control =\n\t\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA,\n\t\t\t\t     WLAN_FC_STYPE_NULLFUNC);\n\t\tsize = sizeof(struct ieee80211_hdr);\n\t}\n\n\tnulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);\n\tos_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);\n\tos_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);\n\tos_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);\n\n\tif (wpa_driver_capwap_send_mlme(bss, (u8 *) &nulldata, size) < 0)\n\t\twpa_printf(MSG_DEBUG, \"capwap_send_null_frame: Failed to \"\n\t\t\t   \"send poll frame\");\n}\n\n\n#ifdef CONFIG_TDLS\n\nstatic int capwap_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,\n\t\t\t\t  u8 dialog_token, u16 status_code,\n\t\t\t\t  const u8 *buf, size_t len)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n\t\treturn -EOPNOTSUPP;\n\n\tif (!dst)\n\t\treturn -EINVAL;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);\n\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);\n\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);\n\tNLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);\n\tNLA_PUT(msg, NL80211_ATTR_IE, len, buf);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int capwap_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tenum capwap_tdls_operation capwap_oper;\n\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n\t\treturn -EOPNOTSUPP;\n\n\tswitch (oper) {\n\tcase TDLS_DISCOVERY_REQ:\n\t\tcapwap_oper = NL80211_TDLS_DISCOVERY_REQ;\n\t\tbreak;\n\tcase TDLS_SETUP:\n\t\tcapwap_oper = NL80211_TDLS_SETUP;\n\t\tbreak;\n\tcase TDLS_TEARDOWN:\n\t\tcapwap_oper = NL80211_TDLS_TEARDOWN;\n\t\tbreak;\n\tcase TDLS_ENABLE_LINK:\n\t\tcapwap_oper = NL80211_TDLS_ENABLE_LINK;\n\t\tbreak;\n\tcase TDLS_DISABLE_LINK:\n\t\tcapwap_oper = NL80211_TDLS_DISABLE_LINK;\n\t\tbreak;\n\tcase TDLS_ENABLE:\n\t\treturn 0;\n\tcase TDLS_DISABLE:\n\t\treturn 0;\n\tdefault:\n\t\treturn -EINVAL;\n\t}\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);\n\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, capwap_oper);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n#endif /* CONFIG TDLS */\nvoid AC_inject_frame_in_hostapd(void *priv, u8 *buf, int len){\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\tint datarate = 0, ssi_signal = 0;\n\tint failed = 0;\n\n\tif (len < 24) {\n\t\tperror(\"recv\");\n\t\treturn;\n\t}\n\n\tint type = AC_get_Type(buf ,len );\n\n\tif(type == WLAN_FC_TYPE_DATA ) {\n\t\tif( isEAPOL_Frame(buf, len) ) {\n\t\t\tif(isCallBackFrame(buf, len, generic_ac_info.own_mac_addr)) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"EAPOL Data Frame 4 (%d)\\n\",len);\n\t\t\t\thandle_tx_callback(drv->ctx, buf ,len , !failed);\n\t\t\t} else {\n\t\t\t\twpa_printf(MSG_DEBUG, \"EAPOL Data Frame 6 (%d)\\n\",len);\n\t\t\t\tAC_handle_eapol(drv,buf,len);\n\t\t\t}\n\t\t} else {\n\t\t\thandle_frame(drv, buf , len , datarate, ssi_signal);\n\t\t}\n\t}\n\telse if( type == WLAN_FC_TYPE_MGMT ){\n\t\tint stype = AC_get_SubType(buf ,len );\n\n\t\t/* Per ora scarto i pacchetti PROBE REQUEST */\n\t\tif(stype == WLAN_FC_STYPE_PROBE_REQ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif(isCallBackFrame(buf,len,generic_ac_info.own_mac_addr)) {\n\t\t\thandle_tx_callback(drv->ctx, buf ,len , !failed);\n\n\t\t\tif( stype == WLAN_FC_STYPE_ASSOC_RESP || stype == WLAN_FC_STYPE_REASSOC_RESP ){\n\t\t\t\tipc_send_add_station(generic_ac_info.fd_ipc,buf,len);\n\t\t\t}\n\t\t}else{\n\t\t\thandle_frame(drv, buf , len , datarate, ssi_signal);\n\n\t\t\tif( stype == WLAN_FC_STYPE_DISASSOC ){\n\t\t\t\tipc_send_del_station(generic_ac_info.fd_ipc, buf, len);\n\t\t\t}\n\t\t}\n\t}else{\n\t\twpa_printf(MSG_ERROR,\"Error: invalid/control 802.11 Type \");\n\t}\n}\n\n\nconst struct wpa_driver_ops wpa_driver_capwap_ops = {\n\t.name = \"capwap\",\n\t.desc = \"Linux capwap/cfg80211\",\n\t.get_bssid = wpa_driver_capwap_get_bssid,\n\t.get_ssid = wpa_driver_capwap_get_ssid,\n\t.set_key = wpa_driver_capwap_set_key,\n\t.scan2 = wpa_driver_capwap_scan,\n\t.sched_scan = wpa_driver_capwap_sched_scan,\n\t.stop_sched_scan = wpa_driver_capwap_stop_sched_scan,\n\t.get_scan_results2 = wpa_driver_capwap_get_scan_results,\n\t.deauthenticate = wpa_driver_capwap_deauthenticate,\n\t.disassociate = wpa_driver_capwap_disassociate,\n\t.authenticate = wpa_driver_capwap_authenticate,\n\t.associate = wpa_driver_capwap_associate,\n\t.global_init = capwap_global_init,\n\t.global_deinit = capwap_global_deinit,\n\t.init2 = wpa_driver_capwap_init,\n\t.deinit = wpa_driver_capwap_deinit,\n\t.get_capa = wpa_driver_capwap_get_capa,\n\t.set_operstate = wpa_driver_capwap_set_operstate,\n\t.set_supp_port = wpa_driver_capwap_set_supp_port,\n\t.set_country = wpa_driver_capwap_set_country,\n\t.set_ap = wpa_driver_capwap_set_ap,\n\t.if_add = wpa_driver_capwap_if_add,\n\t.if_remove = wpa_driver_capwap_if_remove,\n\t.send_mlme = wpa_driver_capwap_send_mlme,\n\t.get_hw_feature_data = wpa_driver_capwap_get_hw_feature_data,\n\t.sta_add = wpa_driver_capwap_sta_add,\n\t.sta_remove = wpa_driver_capwap_sta_remove,\n\t.hapd_send_eapol = wpa_driver_capwap_hapd_send_eapol,\n\t.sta_set_flags = wpa_driver_capwap_sta_set_flags,\n\t//.inject_frame_in_hostapd = AC_inject_frame_in_hostapd,\n#ifdef HOSTAPD\n\t.hapd_init = i802_init,\n\t.hapd_deinit = i802_deinit,\n\t.set_wds_sta = i802_set_wds_sta,\n#endif /* HOSTAPD */\n#if defined(HOSTAPD) || defined(CONFIG_AP)\n\t.get_seqnum = i802_get_seqnum,\n\t.flush = i802_flush,\n\t.read_sta_data = i802_read_sta_data,\n\t.get_inact_sec = i802_get_inact_sec,\n\t.sta_clear_stats = i802_sta_clear_stats,\n\t.set_rts = i802_set_rts,\n\t.set_frag = i802_set_frag,\n\t.set_tx_queue_params = i802_set_tx_queue_params,\n\t.set_sta_vlan = i802_set_sta_vlan,\n\t.set_rate_sets = i802_set_rate_sets,\n\t.sta_deauth = i802_sta_deauth,\n\t.sta_disassoc = i802_sta_disassoc,\n#endif /* HOSTAPD || CONFIG_AP */\n\t.set_freq = i802_set_freq,\n\t.send_action = wpa_driver_capwap_send_action,\n\t.send_action_cancel_wait = wpa_driver_capwap_send_action_cancel_wait,\n\t.remain_on_channel = wpa_driver_capwap_remain_on_channel,\n\t.cancel_remain_on_channel = wpa_driver_capwap_cancel_remain_on_channel,\n\t.probe_req_report = wpa_driver_capwap_probe_req_report,\n\t.deinit_ap = wpa_driver_capwap_deinit_ap,\n\t.deinit_p2p_cli = wpa_driver_capwap_deinit_p2p_cli,\n\t.resume = wpa_driver_capwap_resume,\n\t.send_ft_action = capwap_send_ft_action,\n\t.signal_monitor = capwap_signal_monitor,\n\t.signal_poll = capwap_signal_poll,\n\t.send_frame = capwap_send_frame,\n\t.set_param = capwap_set_param,\n\t.get_radio_name = capwap_get_radio_name,\n\t.add_pmkid = capwap_add_pmkid,\n\t.remove_pmkid = capwap_remove_pmkid,\n\t.flush_pmkid = capwap_flush_pmkid,\n\t.set_rekey_info = capwap_set_rekey_info,\n\t.poll_client = capwap_poll_client,\n#ifdef CONFIG_TDLS\n\t.send_tdls_mgmt = capwap_send_tdls_mgmt,\n\t.tdls_oper = capwap_tdls_oper,\n#endif /* CONFIG_TDLS */\n\n};\n"
  },
  {
    "path": "hostapd_wrapper/src/drivers/driver_capwap_wtp.c",
    "content": "/*\n * Driver interaction with Linux capwap/cfg80211\n * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>\n * Copyright (c) 2003-2004, Instant802 Networks, Inc.\n * Copyright (c) 2005-2006, Devicescape Software, Inc.\n * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>\n * Copyright (c) 2009-2010, Atheros Communications\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n#include \"includes.h\"\n#include <sys/ioctl.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <net/if.h>\n#include <netlink/genl/genl.h>\n#include <netlink/genl/family.h>\n#include <netlink/genl/ctrl.h>\n#include <linux/rtnetlink.h>\n#include <netpacket/packet.h>\n#include <linux/filter.h>\n#include <string.h>\n#include <unistd.h>\n#include <stdio.h>\n#include <sys/socket.h>\n#include <netinet/ip.h>\n#include <netinet/ip_icmp.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <netdb.h>\n#include \"nl80211_copy.h\"\n\n\n#include \"common.h\"\n#include \"eloop.h\"\n#include \"utils/list.h\"\n#include \"common/ieee802_11_defs.h\"\n#include \"common/ieee802_11_common.h\"\n#include \"l2_packet/l2_packet.h\"\n\n#include \"capwap/capwap_mgmt_frame_wtp.h\"\n#include \"capwap/switch_8023_80211.h\"\n#include \"capwap/ipc_capwap_wtp.h\"\n\n#include \"netlink.h\"\n#include \"linux_ioctl.h\"\n#include \"radiotap.h\"\n#include \"radiotap_iter.h\"\n#include \"rfkill.h\"\n#include \"driver.h\"\n\n\n#define BUFFER_SIZE 65000\n//u8 tap_buffer[BUFFER_SIZE];\n\nstruct wtp_info {\n/* capwap FIXME: unused\n\tchar *tap_interface;\n\tchar *wlan_interface;\n\tchar *br_interface;\n*/\n\tu8 own_mac_addr[ETH_ALEN];\n\tint fd_tap;\n\tint fd_udp;\n\tint fd_ipc;\n};\n\nstruct priv_params {\n\tunsigned char ssid[32];\n\tint ssid_len;\n\tunsigned char capa_buf[21];\n};\n\nstruct priv_params ac_params;\n\nvoid stampa_buffer(u8 *buf, int len){\n\tint i;\n\tfor(i=0; i<len; i++){\n\t\tprintf(\"%02X \",buf[i]);\n\t}\n\tprintf(\"\\n\");\n}\n\nvoid WTP_inject_frame_in_air(void *priv, unsigned char *buf, int len);\n\nstruct wtp_info generic_wtp_info;\n\n#ifdef CONFIG_LIBNL20\n/* libnl 2.0 compatibility code */\n#define nl_handle nl_sock\n#define capwap_handle_alloc nl_socket_alloc_cb\n#define capwap_handle_destroy nl_socket_free\n#else\n/*\n * libnl 1.1 has a bug, it tries to allocate socket numbers densely\n * but when you free a socket again it will mess up its bitmap and\n * and use the wrong number the next time it needs a socket ID.\n * Therefore, we wrap the handle alloc/destroy and add our own pid\n * accounting.\n */\nstatic uint32_t port_bitmap[32] = { 0 };\n\n\nstatic struct nl_handle *capwap_handle_alloc(void *cb)\n{\n\tstruct nl_handle *handle;\n\tuint32_t pid = getpid() & 0x3FFFFF;\n\tint i;\n\n\thandle = nl_handle_alloc_cb(cb);\n\n\tfor (i = 0; i < 1024; i++) {\n\t\tif (port_bitmap[i / 32] & (1 << (i % 32)))\n\t\t\tcontinue;\n\t\tport_bitmap[i / 32] |= 1 << (i % 32);\n\t\tpid += i << 22;\n\t\tbreak;\n\t}\n\n\tnl_socket_set_local_port(handle, pid);\n\n\treturn handle;\n}\n\nstatic void capwap_handle_destroy(struct nl_handle *handle)\n{\n\tuint32_t port = nl_socket_get_local_port(handle);\n\n\tport >>= 22;\n\tport_bitmap[port / 32] &= ~(1 << (port % 32));\n\n\tnl_handle_destroy(handle);\n}\n\nstatic inline int __genl_ctrl_alloc_cache(struct nl_handle *h,\n\t\t\t\t\t  struct nl_cache **cache)\n{\n\tstruct nl_cache *tmp = genl_ctrl_alloc_cache(h);\n\tif (!tmp)\n\t\treturn -ENOMEM;\n\t*cache = tmp;\n\treturn 0;\n}\n#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache\n#endif /* CONFIG_LIBNL20 */\n\n\nstruct capwap_handles {\n\tstruct nl_handle *handle;\n\tstruct nl_cache *cache;\n};\n\nstatic int nl_create_handles(struct capwap_handles *handles, struct nl_cb *cb,\n\t\t\t     const char *dbg)\n{\n\n\tif (!handles)\n\t\treturn -1;\n\n\thandles->handle = capwap_handle_alloc(cb);\n\n\tif (handles->handle == NULL) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate netlink \"\n\t\t\t   \"callbacks (%s)\", dbg);\n\t\treturn -1;\n\t}\n\n\tif (genl_connect(handles->handle)) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to connect to generic \"\n\t\t\t   \"netlink (%s)\", dbg);\n\t\tgoto err;\n\t}\n\n\tif (genl_ctrl_alloc_cache(handles->handle, &handles->cache) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate generic \"\n\t\t\t   \"netlink cache (%s)\", dbg);\n\t\tgoto err;\n\t}\n\n\treturn 0;\nerr:\n\tcapwap_handle_destroy(handles->handle);\n\treturn -1;\n\n}\n\n\nstatic void nl_destroy_handles(struct capwap_handles *handles)\n{\n\tif (handles->handle == NULL)\n\t\treturn;\n\tnl_cache_free(handles->cache);\n\tcapwap_handle_destroy(handles->handle);\n\thandles->handle = NULL;\n}\n\n\n#ifndef IFF_LOWER_UP\n#define IFF_LOWER_UP   0x10000         /* driver signals L1 up         */\n#endif\n#ifndef IFF_DORMANT\n#define IFF_DORMANT    0x20000         /* driver signals dormant       */\n#endif\n\n#ifndef IF_OPER_DORMANT\n#define IF_OPER_DORMANT 5\n#endif\n#ifndef IF_OPER_UP\n#define IF_OPER_UP 6\n#endif\n\nstruct capwap_global {\n\tstruct dl_list interfaces;\n\tint if_add_ifindex;\n\tstruct netlink_data *netlink;\n\tstruct nl_cb *nl_cb;\n\tstruct capwap_handles nl;\n\tstruct genl_family *capwap;\n\tint ioctl_sock; /* socket for ioctl() use */\n};\n\nstatic void capwap_global_deinit(void *priv);\nstatic void wpa_driver_capwap_deinit(void *priv);\n\nstruct i802_bss {\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct i802_bss *next;\n\tint ifindex;\n\tchar ifname[IFNAMSIZ + 1];\n\tchar brname[IFNAMSIZ];\n\tunsigned int beacon_set:1;\n\tunsigned int added_if_into_bridge:1;\n\tunsigned int added_bridge:1;\n};\n\nstruct wpa_driver_capwap_data {\n\tstruct capwap_global *global;\n\tstruct dl_list list;\n\tu8 addr[ETH_ALEN];\n\tchar phyname[32];\n\tvoid *ctx;\n\tint ifindex;\n\tint if_removed;\n\tint if_disabled;\n\tint ignore_if_down_event;\n\tstruct rfkill_data *rfkill;\n\tstruct wpa_driver_capa capa;\n\tint has_capability;\n\n\tint operstate;\n\n\tint scan_complete_events;\n\n\tstruct capwap_handles nl_event, nl_preq;\n\n\tu8 auth_bssid[ETH_ALEN];\n\tu8 bssid[ETH_ALEN];\n\tint associated;\n\tu8 ssid[32];\n\tsize_t ssid_len;\n\tenum nl80211_iftype nlmode;\n\tenum nl80211_iftype ap_scan_as_station;\n\tunsigned int assoc_freq;\n\n\tint monitor_sock;\n\tint monitor_ifidx;\n\tint no_monitor_iface_capab;\n\n\tunsigned int disabled_11b_rates:1;\n\tunsigned int pending_remain_on_chan:1;\n\tunsigned int in_interface_list:1;\n\n\tu64 remain_on_chan_cookie;\n\tu64 send_action_cookie;\n\n\tunsigned int last_mgmt_freq;\n\tunsigned int ap_oper_freq;\n\n\tstruct wpa_driver_scan_filter *filter_ssids;\n\tsize_t num_filter_ssids;\n\n\tstruct i802_bss first_bss;\n\n#ifdef CONFIG_AP\n\tstruct l2_packet_data *l2;\n#endif /* CONFIG_AP */\n\n#ifdef HOSTAPD\n\tint eapol_sock; /* socket for EAPOL frames */\n\n\tint default_if_indices[16];\n\tint *if_indices;\n\tint num_if_indices;\n\n\tint last_freq;\n\tint last_freq_ht;\n#endif /* HOSTAPD */\n\n#define CW_LOCAL_MAC   0\n#define CW_SPLIT_MAC   1\n\tint mac_mode;\n};\n\n\nstatic void wpa_driver_capwap_scan_timeout(void *eloop_ctx,\n\t\t\t\t\t    void *timeout_ctx);\nstatic int wpa_driver_capwap_set_mode(struct i802_bss *bss,\n\t\t\t\t       enum nl80211_iftype nlmode);\nstatic int\nwpa_driver_capwap_finish_drv_init(struct wpa_driver_capwap_data *drv);\nstatic int wpa_driver_capwap_mlme(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   const u8 *addr, int cmd, u16 reason_code,\n\t\t\t\t   int local_state_change);\nstatic void capwap_remove_monitor_interface(\n\tstruct wpa_driver_capwap_data *drv);\nstatic int capwap_send_frame_cmd(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  unsigned int freq, unsigned int wait,\n\t\t\t\t  const u8 *buf, size_t buf_len, u64 *cookie,\n\t\t\t\t  int no_cck);\nstatic int wpa_driver_capwap_probe_req_report(void *priv, int report);\n\n#ifdef HOSTAPD\nstatic void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\nstatic void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\nstatic int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx);\nstatic int wpa_driver_capwap_if_remove(void *priv,\n\t\t\t\t\tenum wpa_driver_if_type type,\n\t\t\t\t\tconst char *ifname);\n#else /* HOSTAPD */\nstatic inline void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n}\n\nstatic inline void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n}\n\nstatic inline int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n\treturn 0;\n}\n#endif /* HOSTAPD */\n\nstatic int i802_set_freq(void *priv, struct hostapd_freq_params *freq);\nstatic int capwap_disable_11b_rates(struct wpa_driver_capwap_data *drv,\n\t\t\t\t     int ifindex, int disabled);\n\nstatic int capwap_leave_ibss(struct wpa_driver_capwap_data *drv);\n\n\nstatic int is_ap_interface(enum nl80211_iftype nlmode)\n{\n\treturn (nlmode == NL80211_IFTYPE_AP ||\n\t\tnlmode == NL80211_IFTYPE_P2P_GO);\n}\n\n\nstatic int is_sta_interface(enum nl80211_iftype nlmode)\n{\n\treturn (nlmode == NL80211_IFTYPE_STATION ||\n\t\tnlmode == NL80211_IFTYPE_P2P_CLIENT);\n}\n\n\nstatic int is_p2p_interface(enum nl80211_iftype nlmode)\n{\n\treturn (nlmode == NL80211_IFTYPE_P2P_CLIENT ||\n\t\tnlmode == NL80211_IFTYPE_P2P_GO);\n}\n\n\nstruct capwap_bss_info_arg {\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct wpa_scan_results *res;\n\tunsigned int assoc_freq;\n\tu8 assoc_bssid[ETH_ALEN];\n};\n\nstatic int bss_info_handler(struct nl_msg *msg, void *arg);\n\n\n/* capwap code */\nstatic int ack_handler(struct nl_msg *msg, void *arg)\n{\n\tint *err = arg;\n\t*err = 0;\n\treturn NL_STOP;\n}\n\nstatic int finish_handler(struct nl_msg *msg, void *arg)\n{\n\tint *ret = arg;\n\t*ret = 0;\n\treturn NL_SKIP;\n}\n\nstatic int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,\n\t\t\t void *arg)\n{\n\tint *ret = arg;\n\t*ret = err->error;\n\treturn NL_SKIP;\n}\n\n\nstatic int no_seq_check(struct nl_msg *msg, void *arg)\n{\n\treturn NL_OK;\n}\n\n\nstatic int send_and_recv(struct wpa_driver_capwap_data *drv,\n\t\t\t struct nl_handle *nl_handle, struct nl_msg *msg,\n\t\t\t int (*valid_handler)(struct nl_msg *, void *),\n\t\t\t void *valid_data)\n{\n\n\tstruct nl_cb *cb;\n\tint err = -ENOMEM;\n\n\tcb = nl_cb_clone(drv->global->nl_cb);\n\tif (!cb)\n\t\tgoto out;\n\n\terr = nl_send_auto_complete(nl_handle, msg);\n\tif (err < 0)\n\t\tgoto out;\n\n\terr = 1;\n\n\tnl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);\n\tnl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);\n\tnl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);\n\n\tif (valid_handler)\n\t\tnl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,\n\t\t\t  valid_handler, valid_data);\n\n\twhile (err > 0)\n\t\tnl_recvmsgs(nl_handle, cb);\n\n out:\n\n\tnl_cb_put(cb);\n\tnlmsg_free(msg);\n\treturn err;\n}\n\n\nstatic int send_and_recv_msgs(struct wpa_driver_capwap_data *drv,\n\t\t\t      struct nl_msg *msg,\n\t\t\t      int (*valid_handler)(struct nl_msg *, void *),\n\t\t\t      void *valid_data)\n{\n\n\treturn send_and_recv(drv, drv->global->nl.handle, msg, valid_handler,\n\t\t\t     valid_data);\n}\n\n\nstruct family_data {\n\tconst char *group;\n\tint id;\n};\n\n\nstatic int family_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct family_data *res = arg;\n\tstruct nlattr *tb[CTRL_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *mcgrp;\n\tint i;\n\n\tnla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb[CTRL_ATTR_MCAST_GROUPS])\n\t\treturn NL_SKIP;\n\n\tnla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {\n\t\tstruct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];\n\t\tnla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),\n\t\t\t  nla_len(mcgrp), NULL);\n\t\tif (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||\n\t\t    !tb2[CTRL_ATTR_MCAST_GRP_ID] ||\n\t\t    os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),\n\t\t\t       res->group,\n\t\t\t       nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)\n\t\t\tcontinue;\n\t\tres->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);\n\t\tbreak;\n\t};\n\n\treturn NL_SKIP;\n}\n\n\nstatic int nl_get_multicast_id(struct wpa_driver_capwap_data *drv,\n\t\t\t       const char *family, const char *group)\n{\n\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\tstruct family_data res = { group, -ENOENT };\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tgenlmsg_put(msg, 0, 0,\n\t\t    genl_ctrl_resolve(drv->global->nl.handle, \"nlctrl\"),\n\t\t    0, 0, CTRL_CMD_GETFAMILY, 0);\n\tNLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);\n\n\tret = send_and_recv_msgs(drv, msg, family_handler, &res);\n\tmsg = NULL;\n\tif (ret == 0)\n\t\tret = res.id;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\n\nstatic void * capwap_cmd(struct wpa_driver_capwap_data *drv,\n\t\t\t  struct nl_msg *msg, int flags, uint8_t cmd)\n{\n\n\n\treturn genlmsg_put(msg, 0, 0, genl_family_get_id(drv->global->capwap),\n\t\t\t   0, flags, cmd, 0);\n\n}\n\n\nstatic int wpa_driver_capwap_get_bssid(void *priv, u8 *bssid)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!drv->associated)\n\t\treturn -1;\n\tos_memcpy(bssid, drv->bssid, ETH_ALEN);\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_get_ssid(void *priv, u8 *ssid)\n{\n\twpa_printf(MSG_DEBUG, \"wpa_driver_capwap_get_ssid\");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!drv->associated)\n\n\t\treturn -1;\n//\tos_memcpy(ssid, drv->ssid, drv->ssid_len);\n\tos_memcpy(ssid, ac_params.ssid, ac_params.ssid_len);\n\n\treturn ac_params.ssid_len;\n}\n\n\nstatic void wpa_driver_capwap_event_link(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t  char *buf, size_t len, int del)\n{\n\n\tunion wpa_event_data event;\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (len > sizeof(event.interface_status.ifname))\n\t\tlen = sizeof(event.interface_status.ifname) - 1;\n\tos_memcpy(event.interface_status.ifname, buf, len);\n\tevent.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :\n\t\tEVENT_INTERFACE_ADDED;\n\n\twpa_printf(MSG_DEBUG, \"RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s\",\n\t\t   del ? \"DEL\" : \"NEW\",\n\t\t   event.interface_status.ifname,\n\t\t   del ? \"removed\" : \"added\");\n\n\tif (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) {\n\t\tif (del) {\n\t\t\tif (drv->if_removed) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: if_removed \"\n\t\t\t\t\t   \"already set - ignore event\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdrv->if_removed = 1;\n\t\t} else {\n\t\t\tif (if_nametoindex(drv->first_bss.ifname) == 0) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Interface %s \"\n\t\t\t\t\t   \"does not exist - ignore \"\n\t\t\t\t\t   \"RTM_NEWLINK\",\n\t\t\t\t\t   drv->first_bss.ifname);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!drv->if_removed) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: if_removed \"\n\t\t\t\t\t   \"already cleared - ignore event\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdrv->if_removed = 0;\n\t\t}\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);\n}\n\n\nstatic int wpa_driver_capwap_own_ifname(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t u8 *buf, size_t len)\n{\n\n\tint attrlen, rta_len;\n\tstruct rtattr *attr;\n\n\tattrlen = len;\n\tattr = (struct rtattr *) buf;\n\n\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n\twhile (RTA_OK(attr, attrlen)) {\n\t\tif (attr->rta_type == IFLA_IFNAME) {\n\t\t\tif (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname)\n\t\t\t    == 0)\n\t\t\t\treturn 1;\n\t\t\telse\n\t\t\t\tbreak;\n\t\t}\n\t\tattr = RTA_NEXT(attr, attrlen);\n\t}\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_own_ifindex(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t  int ifindex, u8 *buf, size_t len)\n{\n\n\tif (drv->ifindex == ifindex)\n\t\treturn 1;\n\n\tif (drv->if_removed && wpa_driver_capwap_own_ifname(drv, buf, len)) {\n\t\tdrv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Update ifindex for a removed \"\n\t\t\t   \"interface\");\n\t\twpa_driver_capwap_finish_drv_init(drv);\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\n\nstatic struct wpa_driver_capwap_data *\ncapwap_find_drv(struct capwap_global *global, int idx, u8 *buf, size_t len)\n{\n\tstruct wpa_driver_capwap_data *drv;\n\tdl_list_for_each(drv, &global->interfaces,\n\t\t\t struct wpa_driver_capwap_data, list) {\n\t\tif (wpa_driver_capwap_own_ifindex(drv, idx, buf, len) ||\n\t\t    have_ifidx(drv, idx))\n\t\t\treturn drv;\n\t}\n\treturn NULL;\n}\n\n\nstatic void wpa_driver_capwap_event_rtm_newlink(void *ctx,\n\t\t\t\t\t\t struct ifinfomsg *ifi,\n\t\t\t\t\t\t u8 *buf, size_t len)\n{\n\n\tstruct capwap_global *global = ctx;\n\tstruct wpa_driver_capwap_data *drv;\n\tint attrlen, rta_len;\n\tstruct rtattr *attr;\n\tu32 brid = 0;\n\tchar namebuf[IFNAMSIZ];\n\n\tdrv = capwap_find_drv(global, ifi->ifi_index, buf, len);\n\tif (!drv) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore event for foreign \"\n\t\t\t   \"ifindex %d\", ifi->ifi_index);\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"RTM_NEWLINK: operstate=%d ifi_flags=0x%x \"\n\t\t   \"(%s%s%s%s)\",\n\t\t   drv->operstate, ifi->ifi_flags,\n\t\t   (ifi->ifi_flags & IFF_UP) ? \"[UP]\" : \"\",\n\t\t   (ifi->ifi_flags & IFF_RUNNING) ? \"[RUNNING]\" : \"\",\n\t\t   (ifi->ifi_flags & IFF_LOWER_UP) ? \"[LOWER_UP]\" : \"\",\n\t\t   (ifi->ifi_flags & IFF_DORMANT) ? \"[DORMANT]\" : \"\");\n\n\tif (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {\n\t\tif (if_indextoname(ifi->ifi_index, namebuf) &&\n\t\t    linux_iface_up(drv->global->ioctl_sock,\n\t\t\t\t   drv->first_bss.ifname) > 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface down \"\n\t\t\t\t   \"event since interface %s is up\", namebuf);\n\t\t\treturn;\n\t\t}\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface down\");\n\t\tif (drv->ignore_if_down_event) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface down \"\n\t\t\t\t   \"event generated by mode change\");\n\t\t\tdrv->ignore_if_down_event = 0;\n\t\t} else {\n\t\t\tdrv->if_disabled = 1;\n\t\t\twpa_supplicant_event(drv->ctx,\n\t\t\t\t\t     EVENT_INTERFACE_DISABLED, NULL);\n\t\t}\n\t}\n\n\tif (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {\n\t\tif (if_indextoname(ifi->ifi_index, namebuf) &&\n\t\t    linux_iface_up(drv->global->ioctl_sock,\n\t\t\t\t   drv->first_bss.ifname) == 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n\t\t\t\t   \"event since interface %s is down\",\n\t\t\t\t   namebuf);\n\t\t} else if (if_nametoindex(drv->first_bss.ifname) == 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n\t\t\t\t   \"event since interface %s does not exist\",\n\t\t\t\t   drv->first_bss.ifname);\n\t\t} else if (drv->if_removed) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore interface up \"\n\t\t\t\t   \"event since interface %s is marked \"\n\t\t\t\t   \"removed\", drv->first_bss.ifname);\n\t\t} else {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Interface up\");\n\t\t\tdrv->if_disabled = 0;\n\t\t\twpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,\n\t\t\t\t\t     NULL);\n\t\t}\n\t}\n\n\t/*\n\t * Some drivers send the association event before the operup event--in\n\t * this case, lifting operstate in wpa_driver_capwap_set_operstate()\n\t * fails. This will hit us when wpa_supplicant does not need to do\n\t * IEEE 802.1X authentication\n\t */\n\tif (drv->operstate == 1 &&\n\t    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&\n\t    !(ifi->ifi_flags & IFF_RUNNING))\n\t\tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,\n\t\t\t\t       -1, IF_OPER_UP);\n\n\tattrlen = len;\n\tattr = (struct rtattr *) buf;\n\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n\twhile (RTA_OK(attr, attrlen)) {\n\t\tif (attr->rta_type == IFLA_IFNAME) {\n\t\t\twpa_driver_capwap_event_link(\n\t\t\t\tdrv,\n\t\t\t\t((char *) attr) + rta_len,\n\t\t\t\tattr->rta_len - rta_len, 0);\n\t\t} else if (attr->rta_type == IFLA_MASTER)\n\t\t\tbrid = nla_get_u32((struct nlattr *) attr);\n\t\tattr = RTA_NEXT(attr, attrlen);\n\t}\n\n\tif (ifi->ifi_family == AF_BRIDGE && brid) {\n\t\t/* device has been added to bridge */\n\t\tif_indextoname(brid, namebuf);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Add ifindex %u for bridge %s\",\n\t\t\t   brid, namebuf);\n\t\tadd_ifidx(drv, brid);\n\t}\n}\n\n\nstatic void wpa_driver_capwap_event_rtm_dellink(void *ctx,\n\t\t\t\t\t\t struct ifinfomsg *ifi,\n\t\t\t\t\t\t u8 *buf, size_t len)\n{\n\tstruct capwap_global *global = ctx;\n\tstruct wpa_driver_capwap_data *drv;\n\tint attrlen, rta_len;\n\tstruct rtattr *attr;\n\tu32 brid = 0;\n\n\tdrv = capwap_find_drv(global, ifi->ifi_index, buf, len);\n\tif (!drv) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore dellink event for \"\n\t\t\t   \"foreign ifindex %d\", ifi->ifi_index);\n\t\treturn;\n\t}\n\n\tattrlen = len;\n\tattr = (struct rtattr *) buf;\n\n\trta_len = RTA_ALIGN(sizeof(struct rtattr));\n\twhile (RTA_OK(attr, attrlen)) {\n\t\tif (attr->rta_type == IFLA_IFNAME) {\n\t\t\twpa_driver_capwap_event_link(\n\t\t\t\tdrv,\n\t\t\t\t((char *) attr) + rta_len,\n\t\t\t\tattr->rta_len - rta_len, 1);\n\t\t} else if (attr->rta_type == IFLA_MASTER)\n\t\t\tbrid = nla_get_u32((struct nlattr *) attr);\n\t\tattr = RTA_NEXT(attr, attrlen);\n\t}\n\n\tif (ifi->ifi_family == AF_BRIDGE && brid) {\n\t\t/* device has been removed from bridge */\n\t\tchar namebuf[IFNAMSIZ];\n\t\tif_indextoname(brid, namebuf);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Remove ifindex %u for bridge \"\n\t\t\t   \"%s\", brid, namebuf);\n\t\tdel_ifidx(drv, brid);\n\t}\n}\n\n\nstatic void mlme_event_auth(struct wpa_driver_capwap_data *drv,\n\t\t\t    const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len < 24 + sizeof(mgmt->u.auth)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Too short association event \"\n\t\t\t   \"frame\");\n\t\treturn;\n\t}\n\n\tos_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);\n\tos_memset(&event, 0, sizeof(event));\n\tos_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);\n\tevent.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);\n\tevent.auth.status_code = le_to_host16(mgmt->u.auth.status_code);\n\tif (len > 24 + sizeof(mgmt->u.auth)) {\n\t\tevent.auth.ies = mgmt->u.auth.variable;\n\t\tevent.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);\n}\n\n\nstatic unsigned int capwap_get_assoc_freq(struct wpa_driver_capwap_data *drv)\n{\n\n\tstruct nl_msg *msg;\n\tint ret;\n\tstruct capwap_bss_info_arg arg;\n\n\tos_memset(&arg, 0, sizeof(arg));\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\targ.drv = drv;\n\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Operating frequency for the \"\n\t\t\t   \"associated BSS from scan results: %u MHz\",\n\t\t\t   arg.assoc_freq);\n\t\treturn arg.assoc_freq ? arg.assoc_freq : drv->assoc_freq;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n\t\t   \"(%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn drv->assoc_freq;\n}\n\n\nstatic void mlme_event_assoc(struct wpa_driver_capwap_data *drv,\n\t\t\t    const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tu16 status;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len < 24 + sizeof(mgmt->u.assoc_resp)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Too short association event \"\n\t\t\t   \"frame\");\n\t\treturn;\n\t}\n\n\tstatus = le_to_host16(mgmt->u.assoc_resp.status_code);\n\tif (status != WLAN_STATUS_SUCCESS) {\n\t\tos_memset(&event, 0, sizeof(event));\n\t\tevent.assoc_reject.bssid = mgmt->bssid;\n\t\tif (len > 24 + sizeof(mgmt->u.assoc_resp)) {\n\t\t\tevent.assoc_reject.resp_ies =\n\t\t\t\t(u8 *) mgmt->u.assoc_resp.variable;\n\t\t\tevent.assoc_reject.resp_ies_len =\n\t\t\t\tlen - 24 - sizeof(mgmt->u.assoc_resp);\n\t\t}\n\t\tevent.assoc_reject.status_code = status;\n\n\t\twpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);\n\t\treturn;\n\t}\n\n\tdrv->associated = 1;\n\tos_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (len > 24 + sizeof(mgmt->u.assoc_resp)) {\n\t\tevent.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;\n\t\tevent.assoc_info.resp_ies_len =\n\t\t\tlen - 24 - sizeof(mgmt->u.assoc_resp);\n\t}\n\n\tevent.assoc_info.freq = drv->assoc_freq;\n\n\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);\n}\n\n\nstatic void mlme_event_connect(struct wpa_driver_capwap_data *drv,\n\t\t\t       enum nl80211_commands cmd, struct nlattr *status,\n\t\t\t       struct nlattr *addr, struct nlattr *req_ie,\n\t\t\t       struct nlattr *resp_ie)\n{\n\n\tunion wpa_event_data event;\n\n\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n\t\t/*\n\t\t * Avoid reporting two association events that would confuse\n\t\t * the core code.\n\t\t */\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore connect event (cmd=%d) \"\n\t\t\t   \"when using userspace SME\", cmd);\n\t\treturn;\n\t}\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (cmd == NL80211_CMD_CONNECT &&\n\t    nla_get_u16(status) != WLAN_STATUS_SUCCESS) {\n\t\tif (addr)\n\t\t\tevent.assoc_reject.bssid = nla_data(addr);\n\t\tif (resp_ie) {\n\t\t\tevent.assoc_reject.resp_ies = nla_data(resp_ie);\n\t\t\tevent.assoc_reject.resp_ies_len = nla_len(resp_ie);\n\t\t}\n\t\tevent.assoc_reject.status_code = nla_get_u16(status);\n\t\twpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);\n\t\treturn;\n\t}\n\n\tdrv->associated = 1;\n\tif (addr)\n\t\tos_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);\n\n\tif (req_ie) {\n\t\tevent.assoc_info.req_ies = nla_data(req_ie);\n\t\tevent.assoc_info.req_ies_len = nla_len(req_ie);\n\t}\n\tif (resp_ie) {\n\t\tevent.assoc_info.resp_ies = nla_data(resp_ie);\n\t\tevent.assoc_info.resp_ies_len = nla_len(resp_ie);\n\t}\n\n\tevent.assoc_info.freq = capwap_get_assoc_freq(drv);\n\n\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);\n}\n\n\nstatic void mlme_event_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct nlattr *reason, struct nlattr *addr)\n{\n\tunion wpa_event_data data;\n\n\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n\t\t/*\n\t\t * Avoid reporting two disassociation events that could\n\t\t * confuse the core code.\n\t\t */\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore disconnect \"\n\t\t\t   \"event when using userspace SME\");\n\t\treturn;\n\t}\n\n\tdrv->associated = 0;\n\tos_memset(&data, 0, sizeof(data));\n\tif (reason)\n\t\tdata.disassoc_info.reason_code = nla_get_u16(reason);\n\twpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data);\n}\n\n\nstatic void mlme_timeout_event(struct wpa_driver_capwap_data *drv,\n\t\t\t       enum nl80211_commands cmd, struct nlattr *addr)\n{\n\tunion wpa_event_data event;\n\tenum wpa_event_type ev;\n\n\tif (nla_len(addr) != ETH_ALEN)\n\t\treturn;\n\n\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d; timeout with \" MACSTR,\n\t\t   cmd, MAC2STR((u8 *) nla_data(addr)));\n\n\tif (cmd == NL80211_CMD_AUTHENTICATE)\n\t\tev = EVENT_AUTH_TIMED_OUT;\n\telse if (cmd == NL80211_CMD_ASSOCIATE)\n\t\tev = EVENT_ASSOC_TIMED_OUT;\n\telse\n\t\treturn;\n\n\tos_memset(&event, 0, sizeof(event));\n\tos_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);\n\twpa_supplicant_event(drv->ctx, ev, &event);\n}\n\n\nstatic void mlme_event_mgmt(struct wpa_driver_capwap_data *drv,\n\t\t\t    struct nlattr *freq, const u8 *frame, size_t len)\n{\n\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tu16 fc, stype;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len < 24) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Too short action frame\");\n\t\treturn;\n\t}\n\n\tfc = le_to_host16(mgmt->frame_control);\n\tstype = WLAN_FC_GET_STYPE(fc);\n\n\tos_memset(&event, 0, sizeof(event));\n\tif (freq) {\n\t\tevent.rx_action.freq = nla_get_u32(freq);\n\t\tdrv->last_mgmt_freq = event.rx_action.freq;\n\t}\n\tif (stype == WLAN_FC_STYPE_ACTION) {\n\t\tevent.rx_action.da = mgmt->da;\n\t\tevent.rx_action.sa = mgmt->sa;\n\t\tevent.rx_action.bssid = mgmt->bssid;\n\t\tevent.rx_action.category = mgmt->u.action.category;\n\t\tevent.rx_action.data = &mgmt->u.action.category + 1;\n\t\tevent.rx_action.len = frame + len - event.rx_action.data;\n\t\twpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);\n\t} else {\n\t\tevent.rx_mgmt.frame = frame;\n\t\tevent.rx_mgmt.frame_len = len;\n\t\twpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);\n\t}\n}\n\n\nstatic void mlme_event_action_tx_status(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\tstruct nlattr *cookie, const u8 *frame,\n\t\t\t\t\tsize_t len, struct nlattr *ack)\n{\n\tunion wpa_event_data event;\n\tconst struct ieee80211_hdr *hdr;\n\tu16 fc;\n\tu64 cookie_val;\n\n\tif (!cookie)\n\t\treturn;\n\n\tcookie_val = nla_get_u64(cookie);\n\twpa_printf(MSG_DEBUG, \"capwap: Action TX status: cookie=0%llx%s \"\n\t\t   \"(ack=%d)\",\n\t\t   (long long unsigned int) cookie_val,\n\t\t   cookie_val == drv->send_action_cookie ?\n\t\t   \" (match)\" : \" (unknown)\", ack != NULL);\n\tif (cookie_val != drv->send_action_cookie)\n\t\treturn;\n\n\thdr = (const struct ieee80211_hdr *) frame;\n\tfc = le_to_host16(hdr->frame_control);\n\n\tos_memset(&event, 0, sizeof(event));\n\tevent.tx_status.type = WLAN_FC_GET_TYPE(fc);\n\tevent.tx_status.stype = WLAN_FC_GET_STYPE(fc);\n\tevent.tx_status.dst = hdr->addr1;\n\tevent.tx_status.data = frame;\n\tevent.tx_status.data_len = len;\n\tevent.tx_status.ack = ack != NULL;\n\twpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);\n}\n\n\nstatic void mlme_event_deauth_disassoc(struct wpa_driver_capwap_data *drv,\n\t\t\t\t       enum wpa_event_type type,\n\t\t\t\t       const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tconst u8 *bssid = NULL;\n\tu16 reason_code = 0;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\tif (len >= 24) {\n\t\tbssid = mgmt->bssid;\n\n\t\tif (drv->associated != 0 &&\n\t\t    os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&\n\t\t    os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {\n\t\t\t/*\n\t\t\t * We have presumably received this deauth as a\n\t\t\t * response to a clear_state_mismatch() outgoing\n\t\t\t * deauth.  Don't let it take us offline!\n\t\t\t */\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Deauth received \"\n\t\t\t\t   \"from Unknown BSSID \" MACSTR \" -- ignoring\",\n\t\t\t\t   MAC2STR(bssid));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tdrv->associated = 0;\n\tos_memset(&event, 0, sizeof(event));\n\n\t/* Note: Same offset for Reason Code in both frame subtypes */\n\tif (len >= 24 + sizeof(mgmt->u.deauth))\n\t\treason_code = le_to_host16(mgmt->u.deauth.reason_code);\n\n\tif (type == EVENT_DISASSOC) {\n\t\tevent.disassoc_info.addr = bssid;\n\t\tevent.disassoc_info.reason_code = reason_code;\n\t\tif (frame + len > mgmt->u.disassoc.variable) {\n\t\t\tevent.disassoc_info.ie = mgmt->u.disassoc.variable;\n\t\t\tevent.disassoc_info.ie_len = frame + len -\n\t\t\t\tmgmt->u.disassoc.variable;\n\t\t}\n\t} else {\n\t\tevent.deauth_info.addr = bssid;\n\t\tevent.deauth_info.reason_code = reason_code;\n\t\tif (frame + len > mgmt->u.deauth.variable) {\n\t\t\tevent.deauth_info.ie = mgmt->u.deauth.variable;\n\t\t\tevent.deauth_info.ie_len = frame + len -\n\t\t\t\tmgmt->u.deauth.variable;\n\t\t}\n\t}\n\n\twpa_supplicant_event(drv->ctx, type, &event);\n}\n\n\nstatic void mlme_event_unprot_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t enum wpa_event_type type,\n\t\t\t\t\t const u8 *frame, size_t len)\n{\n\tconst struct ieee80211_mgmt *mgmt;\n\tunion wpa_event_data event;\n\tu16 reason_code = 0;\n\n\tif (len < 24)\n\t\treturn;\n\n\tmgmt = (const struct ieee80211_mgmt *) frame;\n\n\tos_memset(&event, 0, sizeof(event));\n\t/* Note: Same offset for Reason Code in both frame subtypes */\n\tif (len >= 24 + sizeof(mgmt->u.deauth))\n\t\treason_code = le_to_host16(mgmt->u.deauth.reason_code);\n\n\tif (type == EVENT_UNPROT_DISASSOC) {\n\t\tevent.unprot_disassoc.sa = mgmt->sa;\n\t\tevent.unprot_disassoc.da = mgmt->da;\n\t\tevent.unprot_disassoc.reason_code = reason_code;\n\t} else {\n\t\tevent.unprot_deauth.sa = mgmt->sa;\n\t\tevent.unprot_deauth.da = mgmt->da;\n\t\tevent.unprot_deauth.reason_code = reason_code;\n\t}\n\n\twpa_supplicant_event(drv->ctx, type, &event);\n}\n\n\nstatic void mlme_event(struct wpa_driver_capwap_data *drv,\n\t\t       enum nl80211_commands cmd, struct nlattr *frame,\n\t\t       struct nlattr *addr, struct nlattr *timed_out,\n\t\t       struct nlattr *freq, struct nlattr *ack,\n\t\t       struct nlattr *cookie)\n{\n\tif (timed_out && addr) {\n\t\tmlme_timeout_event(drv, cmd, addr);\n\t\treturn;\n\t}\n\n\tif (frame == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d without frame \"\n\t\t\t   \"data\", cmd);\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: MLME event %d\", cmd);\n\twpa_hexdump(MSG_MSGDUMP, \"capwap: MLME event frame\",\n\t\t    nla_data(frame), nla_len(frame));\n\n\tswitch (cmd) {\n\tcase NL80211_CMD_AUTHENTICATE:\n\t\tmlme_event_auth(drv, nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_ASSOCIATE:\n\t\tmlme_event_assoc(drv, nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_DEAUTHENTICATE:\n\t\tmlme_event_deauth_disassoc(drv, EVENT_DEAUTH,\n\t\t\t\t\t   nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_DISASSOCIATE:\n\t\tmlme_event_deauth_disassoc(drv, EVENT_DISASSOC,\n\t\t\t\t\t   nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_FRAME:\n\t\tmlme_event_mgmt(drv, freq, nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_FRAME_TX_STATUS:\n\t\tmlme_event_action_tx_status(drv, cookie, nla_data(frame),\n\t\t\t\t\t    nla_len(frame), ack);\n\t\tbreak;\n\tcase NL80211_CMD_UNPROT_DEAUTHENTICATE:\n\t\tmlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,\n\t\t\t\t\t     nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tcase NL80211_CMD_UNPROT_DISASSOCIATE:\n\t\tmlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,\n\t\t\t\t\t     nla_data(frame), nla_len(frame));\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n\nstatic void mlme_event_michael_mic_failure(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t   struct nlattr *tb[])\n{\n\tunion wpa_event_data data;\n\n\twpa_printf(MSG_DEBUG, \"capwap: MLME event Michael MIC failure\");\n\tos_memset(&data, 0, sizeof(data));\n\tif (tb[NL80211_ATTR_MAC]) {\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: Source MAC address\",\n\t\t\t    nla_data(tb[NL80211_ATTR_MAC]),\n\t\t\t    nla_len(tb[NL80211_ATTR_MAC]));\n\t\tdata.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);\n\t}\n\tif (tb[NL80211_ATTR_KEY_SEQ]) {\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: TSC\",\n\t\t\t    nla_data(tb[NL80211_ATTR_KEY_SEQ]),\n\t\t\t    nla_len(tb[NL80211_ATTR_KEY_SEQ]));\n\t}\n\tif (tb[NL80211_ATTR_KEY_TYPE]) {\n\t\tenum nl80211_key_type key_type =\n\t\t\tnla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Key Type %d\", key_type);\n\t\tif (key_type == NL80211_KEYTYPE_PAIRWISE)\n\t\t\tdata.michael_mic_failure.unicast = 1;\n\t} else\n\t\tdata.michael_mic_failure.unicast = 1;\n\n\tif (tb[NL80211_ATTR_KEY_IDX]) {\n\t\tu8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);\n\t\twpa_printf(MSG_DEBUG, \"capwap: Key Id %d\", key_id);\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);\n}\n\n\nstatic void mlme_event_join_ibss(struct wpa_driver_capwap_data *drv,\n\t\t\t\t struct nlattr *tb[])\n{\n\tif (tb[NL80211_ATTR_MAC] == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No address in IBSS joined \"\n\t\t\t   \"event\");\n\t\treturn;\n\t}\n\tos_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);\n\tdrv->associated = 1;\n\twpa_printf(MSG_DEBUG, \"capwap: IBSS \" MACSTR \" joined\",\n\t\t   MAC2STR(drv->bssid));\n\n\twpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);\n}\n\n\nstatic void mlme_event_remain_on_channel(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t int cancel_event, struct nlattr *tb[])\n{\n\tunsigned int freq, chan_type, duration;\n\tunion wpa_event_data data;\n\tu64 cookie;\n\n\tif (tb[NL80211_ATTR_WIPHY_FREQ])\n\t\tfreq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);\n\telse\n\t\tfreq = 0;\n\n\tif (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])\n\t\tchan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);\n\telse\n\t\tchan_type = 0;\n\n\tif (tb[NL80211_ATTR_DURATION])\n\t\tduration = nla_get_u32(tb[NL80211_ATTR_DURATION]);\n\telse\n\t\tduration = 0;\n\n\tif (tb[NL80211_ATTR_COOKIE])\n\t\tcookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);\n\telse\n\t\tcookie = 0;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Remain-on-channel event (cancel=%d \"\n\t\t   \"freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))\",\n\t\t   cancel_event, freq, chan_type, duration,\n\t\t   (long long unsigned int) cookie,\n\t\t   cookie == drv->remain_on_chan_cookie ? \"match\" : \"unknown\");\n\n\tif (cookie != drv->remain_on_chan_cookie)\n\t\treturn; /* not for us */\n\n\tif (cancel_event)\n\t\tdrv->pending_remain_on_chan = 0;\n\n\tos_memset(&data, 0, sizeof(data));\n\tdata.remain_on_channel.freq = freq;\n\tdata.remain_on_channel.duration = duration;\n\twpa_supplicant_event(drv->ctx, cancel_event ?\n\t\t\t     EVENT_CANCEL_REMAIN_ON_CHANNEL :\n\t\t\t     EVENT_REMAIN_ON_CHANNEL, &data);\n}\n\n\nstatic void send_scan_event(struct wpa_driver_capwap_data *drv, int aborted,\n\t\t\t    struct nlattr *tb[])\n{\n\tunion wpa_event_data event;\n\tstruct nlattr *nl;\n\tint rem;\n\tstruct scan_info *info;\n#define MAX_REPORT_FREQS 50\n\tint freqs[MAX_REPORT_FREQS];\n\tint num_freqs = 0;\n\n\tos_memset(&event, 0, sizeof(event));\n\tinfo = &event.scan_info;\n\tinfo->aborted = aborted;\n\n\tif (tb[NL80211_ATTR_SCAN_SSIDS]) {\n\t\tnla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {\n\t\t\tstruct wpa_driver_scan_ssid *s =\n\t\t\t\t&info->ssids[info->num_ssids];\n\t\t\ts->ssid = nla_data(nl);\n\t\t\ts->ssid_len = nla_len(nl);\n\t\t\tinfo->num_ssids++;\n\t\t\tif (info->num_ssids == WPAS_MAX_SCAN_SSIDS)\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {\n\t\tnla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)\n\t\t{\n\t\t\tfreqs[num_freqs] = nla_get_u32(nl);\n\t\t\tnum_freqs++;\n\t\t\tif (num_freqs == MAX_REPORT_FREQS - 1)\n\t\t\t\tbreak;\n\t\t}\n\t\tinfo->freqs = freqs;\n\t\tinfo->num_freqs = num_freqs;\n\t}\n\twpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);\n}\n\n\nstatic int get_link_signal(struct nl_msg *msg, void *arg)\n{\n\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];\n\tstatic struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {\n\t\t[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },\n\t};\n\tstruct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];\n\tstatic struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {\n\t\t[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },\n\t\t[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },\n\t\t[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },\n\t\t[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },\n\t};\n\tstruct wpa_signal_info *sig_change = arg;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb[NL80211_ATTR_STA_INFO] ||\n\t    nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_STA_INFO], policy))\n\t\treturn NL_SKIP;\n\tif (!sinfo[NL80211_STA_INFO_SIGNAL])\n\t\treturn NL_SKIP;\n\n\tsig_change->current_signal =\n\t\t(s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);\n\n\tif (sinfo[NL80211_STA_INFO_TX_BITRATE]) {\n\t\tif (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,\n\t\t\t\t     sinfo[NL80211_STA_INFO_TX_BITRATE],\n\t\t\t\t     rate_policy)) {\n\t\t\tsig_change->current_txrate = 0;\n\t\t} else {\n\t\t\tif (rinfo[NL80211_RATE_INFO_BITRATE]) {\n\t\t\t\tsig_change->current_txrate =\n\t\t\t\t\tnla_get_u16(rinfo[\n\t\t\t\t\t     NL80211_RATE_INFO_BITRATE]) * 100;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_get_link_signal(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   struct wpa_signal_info *sig)\n{\n\n\tstruct nl_msg *msg;\n\n\tsig->current_signal = -9999;\n\tsig->current_txrate = 0;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);\n\n\treturn send_and_recv_msgs(drv, msg, get_link_signal, sig);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int get_link_noise(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];\n\tstatic struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {\n\t\t[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },\n\t\t[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },\n\t};\n\tstruct wpa_signal_info *sig_change = arg;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (!tb[NL80211_ATTR_SURVEY_INFO]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: survey data missing!\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_SURVEY_INFO],\n\t\t\t     survey_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: failed to parse nested \"\n\t\t\t   \"attributes!\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])\n\t\treturn NL_SKIP;\n\n\tif (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=\n\t    sig_change->frequency)\n\t\treturn NL_SKIP;\n\n\tif (!sinfo[NL80211_SURVEY_INFO_NOISE])\n\t\treturn NL_SKIP;\n\n\tsig_change->current_noise =\n\t\t(s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_get_link_noise(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct wpa_signal_info *sig_change)\n{\n\n\tstruct nl_msg *msg;\n\n\tsig_change->current_noise = 9999;\n\tsig_change->frequency = drv->assoc_freq;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\treturn send_and_recv_msgs(drv, msg, get_link_noise, sig_change);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int get_noise_for_scan_results(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];\n\tstatic struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {\n\t\t[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },\n\t\t[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },\n\t};\n\tstruct wpa_scan_results *scan_results = arg;\n\tstruct wpa_scan_res *scan_res;\n\tsize_t i;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (!tb[NL80211_ATTR_SURVEY_INFO]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Survey data missing\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_SURVEY_INFO],\n\t\t\t     survey_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to parse nested \"\n\t\t\t   \"attributes\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (!sinfo[NL80211_SURVEY_INFO_NOISE])\n\t\treturn NL_SKIP;\n\n\tif (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])\n\t\treturn NL_SKIP;\n\n\tfor (i = 0; i < scan_results->num; ++i) {\n\t\tscan_res = scan_results->res[i];\n\t\tif (!scan_res)\n\t\t\tcontinue;\n\t\tif ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=\n\t\t    scan_res->freq)\n\t\t\tcontinue;\n\t\tif (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))\n\t\t\tcontinue;\n\t\tscan_res->noise = (s8)\n\t\t\tnla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);\n\t\tscan_res->flags &= ~WPA_SCAN_NOISE_INVALID;\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_get_noise_for_scan_results(\n\tstruct wpa_driver_capwap_data *drv,\n\tstruct wpa_scan_results *scan_res)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\treturn send_and_recv_msgs(drv, msg, get_noise_for_scan_results,\n\t\t\t\t  scan_res);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic void capwap_cqm_event(struct wpa_driver_capwap_data *drv,\n\t\t\t      struct nlattr *tb[])\n{\n\tstatic struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {\n\t\t[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },\n\t\t[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },\n\t};\n\tstruct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];\n\tenum nl80211_cqm_rssi_threshold_event event;\n\tunion wpa_event_data ed;\n\tstruct wpa_signal_info sig;\n\tint res;\n\n\tif (tb[NL80211_ATTR_CQM] == NULL ||\n\t    nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],\n\t\t\t     cqm_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore invalid CQM event\");\n\t\treturn;\n\t}\n\n\tos_memset(&ed, 0, sizeof(ed));\n\n\tif (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {\n\t\tif (!tb[NL80211_ATTR_MAC])\n\t\t\treturn;\n\t\tos_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),\n\t\t\t  ETH_ALEN);\n\t\twpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);\n\t\treturn;\n\t}\n\n\tif (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)\n\t\treturn;\n\tevent = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);\n\n\tif (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Connection quality monitor \"\n\t\t\t   \"event: RSSI high\");\n\t\ted.signal_change.above_threshold = 1;\n\t} else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Connection quality monitor \"\n\t\t\t   \"event: RSSI low\");\n\t\ted.signal_change.above_threshold = 0;\n\t} else\n\t\treturn;\n\n\tres = capwap_get_link_signal(drv, &sig);\n\tif (res == 0) {\n\t\ted.signal_change.current_signal = sig.current_signal;\n\t\ted.signal_change.current_txrate = sig.current_txrate;\n\t\twpa_printf(MSG_DEBUG, \"capwap: Signal: %d dBm  txrate: %d\",\n\t\t\t   sig.current_signal, sig.current_txrate);\n\t}\n\n\tres = capwap_get_link_noise(drv, &sig);\n\tif (res == 0) {\n\t\ted.signal_change.current_noise = sig.current_noise;\n\t\twpa_printf(MSG_DEBUG, \"capwap: Noise: %d dBm\",\n\t\t\t   sig.current_noise);\n\t}\n\n\twpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);\n}\n\n\nstatic void capwap_new_station_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t      struct nlattr **tb)\n{\n\tu8 *addr;\n\tunion wpa_event_data data;\n\n\tif (tb[NL80211_ATTR_MAC] == NULL)\n\t\treturn;\n\taddr = nla_data(tb[NL80211_ATTR_MAC]);\n\twpa_printf(MSG_DEBUG, \"capwap: New station \" MACSTR, MAC2STR(addr));\n\n\tif (is_ap_interface(drv->nlmode) && drv->no_monitor_iface_capab) {\n\t\tu8 *ies = NULL;\n\t\tsize_t ies_len = 0;\n\t\tif (tb[NL80211_ATTR_IE]) {\n\t\t\ties = nla_data(tb[NL80211_ATTR_IE]);\n\t\t\ties_len = nla_len(tb[NL80211_ATTR_IE]);\n\t\t}\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: Assoc Req IEs\", ies, ies_len);\n\t\tdrv_event_assoc(drv->ctx, addr, ies, ies_len, 0);\n\t\treturn;\n\t}\n\n\tif (drv->nlmode != NL80211_IFTYPE_ADHOC)\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tos_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);\n\twpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);\n}\n\n\nstatic void capwap_del_station_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t      struct nlattr **tb)\n{\n\tu8 *addr;\n\tunion wpa_event_data data;\n\n\tif (tb[NL80211_ATTR_MAC] == NULL)\n\t\treturn;\n\taddr = nla_data(tb[NL80211_ATTR_MAC]);\n\twpa_printf(MSG_DEBUG, \"capwap: Delete station \" MACSTR,\n\t\t   MAC2STR(addr));\n\n\tif (is_ap_interface(drv->nlmode) && drv->no_monitor_iface_capab) {\n\t\tdrv_event_disassoc(drv->ctx, addr);\n\t\treturn;\n\t}\n\n\tif (drv->nlmode != NL80211_IFTYPE_ADHOC)\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tos_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);\n\twpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);\n}\n\n\nstatic void capwap_rekey_offload_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\tstruct nlattr **tb)\n{\n\tstruct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];\n\tstatic struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {\n\t\t[NL80211_REKEY_DATA_KEK] = {\n\t\t\t.minlen = NL80211_KEK_LEN,\n\t\t\t.maxlen = NL80211_KEK_LEN,\n\t\t},\n\t\t[NL80211_REKEY_DATA_KCK] = {\n\t\t\t.minlen = NL80211_KCK_LEN,\n\t\t\t.maxlen = NL80211_KCK_LEN,\n\t\t},\n\t\t[NL80211_REKEY_DATA_REPLAY_CTR] = {\n\t\t\t.minlen = NL80211_REPLAY_CTR_LEN,\n\t\t\t.maxlen = NL80211_REPLAY_CTR_LEN,\n\t\t},\n\t};\n\tunion wpa_event_data data;\n\n\tif (!tb[NL80211_ATTR_MAC])\n\t\treturn;\n\tif (!tb[NL80211_ATTR_REKEY_DATA])\n\t\treturn;\n\tif (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,\n\t\t\t     tb[NL80211_ATTR_REKEY_DATA], rekey_policy))\n\t\treturn;\n\tif (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tdata.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);\n\twpa_printf(MSG_DEBUG, \"capwap: Rekey offload event for BSSID \" MACSTR,\n\t\t   MAC2STR(data.driver_gtk_rekey.bssid));\n\tdata.driver_gtk_rekey.replay_ctr =\n\t\tnla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);\n\twpa_hexdump(MSG_DEBUG, \"capwap: Rekey offload - Replay Counter\",\n\t\t    data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);\n\twpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);\n}\n\n\nstatic void capwap_pmksa_candidate_event(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t  struct nlattr **tb)\n{\n\tstruct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];\n\tstatic struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {\n\t\t[NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },\n\t\t[NL80211_PMKSA_CANDIDATE_BSSID] = {\n\t\t\t.minlen = ETH_ALEN,\n\t\t\t.maxlen = ETH_ALEN,\n\t\t},\n\t\t[NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },\n\t};\n\tunion wpa_event_data data;\n\n\tif (!tb[NL80211_ATTR_PMKSA_CANDIDATE])\n\t\treturn;\n\tif (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,\n\t\t\t     tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))\n\t\treturn;\n\tif (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||\n\t    !cand[NL80211_PMKSA_CANDIDATE_BSSID])\n\t\treturn;\n\n\tos_memset(&data, 0, sizeof(data));\n\tos_memcpy(data.pmkid_candidate.bssid,\n\t\t  nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);\n\tdata.pmkid_candidate.index =\n\t\tnla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);\n\tdata.pmkid_candidate.preauth =\n\t\tcand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;\n\twpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);\n}\n\n\nstatic int process_event(struct nl_msg *msg, void *arg)\n{\n\n\tstruct wpa_driver_capwap_data *drv = arg;\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (tb[NL80211_ATTR_IFINDEX]) {\n\t\tint ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);\n\t\tif (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignored event (cmd=%d)\"\n\t\t\t\t   \" for foreign interface (ifindex %d)\",\n\t\t\t\t   gnlh->cmd, ifindex);\n\t\t\treturn NL_SKIP;\n\t\t}\n\t}\n\n\tif (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&\n\t    (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS ||\n\t     gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) {\n\t\twpa_driver_capwap_set_mode(&drv->first_bss,\n\t\t\t\t\t    drv->ap_scan_as_station);\n\t\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n\t}\n\n\tswitch (gnlh->cmd) {\n\tcase NL80211_CMD_TRIGGER_SCAN:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Scan trigger\");\n\t\tbreak;\n\tcase NL80211_CMD_START_SCHED_SCAN:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan started\");\n\t\tbreak;\n\tcase NL80211_CMD_SCHED_SCAN_STOPPED:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stopped\");\n\t\twpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);\n\t\tbreak;\n\tcase NL80211_CMD_NEW_SCAN_RESULTS:\n\t\twpa_printf(MSG_DEBUG, \"capwap: New scan results available\");\n\t\tdrv->scan_complete_events = 1;\n\t\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv,\n\t\t\t\t     drv->ctx);\n\t\tsend_scan_event(drv, 0, tb);\n\t\tbreak;\n\tcase NL80211_CMD_SCHED_SCAN_RESULTS:\n\t\twpa_printf(MSG_DEBUG,\n\t\t\t   \"capwap: New sched scan results available\");\n\t\tsend_scan_event(drv, 0, tb);\n\t\tbreak;\n\tcase NL80211_CMD_SCAN_ABORTED:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Scan aborted\");\n\t\t/*\n\t\t * Need to indicate that scan results are available in order\n\t\t * not to make wpa_supplicant stop its scanning.\n\t\t */\n\t\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv,\n\t\t\t\t     drv->ctx);\n\t\tsend_scan_event(drv, 1, tb);\n\t\tbreak;\n\tcase NL80211_CMD_AUTHENTICATE:\n\tcase NL80211_CMD_ASSOCIATE:\n\tcase NL80211_CMD_DEAUTHENTICATE:\n\tcase NL80211_CMD_DISASSOCIATE:\n\tcase NL80211_CMD_FRAME:\n\tcase NL80211_CMD_FRAME_TX_STATUS:\n\tcase NL80211_CMD_UNPROT_DEAUTHENTICATE:\n\tcase NL80211_CMD_UNPROT_DISASSOCIATE:\n\t\tmlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],\n\t\t\t   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],\n\t\t\t   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],\n\t\t\t   tb[NL80211_ATTR_COOKIE]);\n\t\tbreak;\n\tcase NL80211_CMD_CONNECT:\n\tcase NL80211_CMD_ROAM:\n\t\tmlme_event_connect(drv, gnlh->cmd,\n\t\t\t\t   tb[NL80211_ATTR_STATUS_CODE],\n\t\t\t\t   tb[NL80211_ATTR_MAC],\n\t\t\t\t   tb[NL80211_ATTR_REQ_IE],\n\t\t\t\t   tb[NL80211_ATTR_RESP_IE]);\n\t\tbreak;\n\tcase NL80211_CMD_DISCONNECT:\n\t\tmlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],\n\t\t\t\t      tb[NL80211_ATTR_MAC]);\n\t\tbreak;\n\tcase NL80211_CMD_MICHAEL_MIC_FAILURE:\n\t\tmlme_event_michael_mic_failure(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_JOIN_IBSS:\n\t\tmlme_event_join_ibss(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_REMAIN_ON_CHANNEL:\n\t\tmlme_event_remain_on_channel(drv, 0, tb);\n\t\tbreak;\n\tcase NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:\n\t\tmlme_event_remain_on_channel(drv, 1, tb);\n\t\tbreak;\n\tcase NL80211_CMD_NOTIFY_CQM:\n\t\tcapwap_cqm_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_REG_CHANGE:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Regulatory domain change\");\n\t\twpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,\n\t\t\t\t     NULL);\n\t\tbreak;\n\tcase NL80211_CMD_REG_BEACON_HINT:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Regulatory beacon hint\");\n\t\twpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,\n\t\t\t\t     NULL);\n\t\tbreak;\n\tcase NL80211_CMD_NEW_STATION:\n\t\tcapwap_new_station_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_DEL_STATION:\n\t\tcapwap_del_station_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_SET_REKEY_OFFLOAD:\n\t\tcapwap_rekey_offload_event(drv, tb);\n\t\tbreak;\n\tcase NL80211_CMD_PMKSA_CANDIDATE:\n\t\tcapwap_pmksa_candidate_event(drv, tb);\n\t\tbreak;\n\tdefault:\n\t\twpa_printf(MSG_DEBUG, \"capwap: Ignored unknown event \"\n\t\t\t   \"(cmd=%d)\", gnlh->cmd);\n\t\tbreak;\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic void wpa_driver_capwap_event_receive(int sock, void *eloop_ctx,\n\t\t\t\t\t     void *handle)\n{\n\twpa_printf(MSG_DEBUG, \"wpa_driver_capwap_event_receive\");\n\tstruct nl_cb *cb;\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Event message available\");\n\n\tcb = nl_cb_clone(drv->global->nl_cb);\n\tif (!cb)\n\t\treturn;\n\tnl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);\n\tnl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv);\n\tnl_recvmsgs(handle, cb);\n\tnl_cb_put(cb);\n}\n\n\n/**\n * wpa_driver_capwap_set_country - ask capwap to set the regulatory domain\n * @priv: driver_capwap private data\n * @alpha2_arg: country to which to switch to\n * Returns: 0 on success, -1 on failure\n *\n * This asks capwap to set the regulatory domain for given\n * country ISO / IEC alpha2.\n */\nstatic int wpa_driver_capwap_set_country(void *priv, const char *alpha2_arg)\n{\n\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tchar alpha2[3];\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\talpha2[0] = alpha2_arg[0];\n\talpha2[1] = alpha2_arg[1];\n\talpha2[2] = '\\0';\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);\n\n\tNLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL))\n\t\treturn -EINVAL;\n\treturn 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -EINVAL;\n}\n\n\nstruct wiphy_info_data {\n\tstruct wpa_driver_capa *capa;\n\n\tunsigned int error:1;\n};\n\n\nstatic int wiphy_info_handler(struct nl_msg *msg, void *arg)\n{\n\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct wiphy_info_data *info = arg;\n\tint p2p_go_supported = 0, p2p_client_supported = 0;\n\tint p2p_concurrent = 0;\n\tint auth_supported = 0, connect_supported = 0;\n\tstruct wpa_driver_capa *capa = info->capa;\n\tstatic struct nla_policy\n\tiface_combination_policy[NUM_NL80211_IFACE_COMB] = {\n\t\t[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },\n\t\t[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },\n\t\t[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },\n\t\t[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },\n\t},\n\tiface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {\n\t\t[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },\n\t\t[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },\n\t};\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])\n\t\tcapa->max_scan_ssids =\n\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);\n\n\tif (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])\n\t\tcapa->max_sched_scan_ssids =\n\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);\n\n\tif (tb[NL80211_ATTR_MAX_MATCH_SETS])\n\t\tcapa->max_match_sets =\n\t\t\tnla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);\n\n\tif (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {\n\t\tstruct nlattr *nl_mode;\n\t\tint i;\n\t\tnla_for_each_nested(nl_mode,\n\t\t\t\t    tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {\n\t\t\tswitch (nla_type(nl_mode)) {\n\t\t\tcase NL80211_IFTYPE_AP:\n\t\t\t\tcapa->flags |= WPA_DRIVER_FLAGS_AP;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_IFTYPE_P2P_GO:\n\t\t\t\tp2p_go_supported = 1;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_IFTYPE_P2P_CLIENT:\n\t\t\t\tp2p_client_supported = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tb[NL80211_ATTR_INTERFACE_COMBINATIONS]) {\n\t\tstruct nlattr *nl_combi;\n\t\tint rem_combi;\n\n\t\tnla_for_each_nested(nl_combi,\n\t\t\t\t    tb[NL80211_ATTR_INTERFACE_COMBINATIONS],\n\t\t\t\t    rem_combi) {\n\t\t\tstruct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];\n\t\t\tstruct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];\n\t\t\tstruct nlattr *nl_limit, *nl_mode;\n\t\t\tint err, rem_limit, rem_mode;\n\t\t\tint combination_has_p2p = 0, combination_has_mgd = 0;\n\n\t\t\terr = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,\n\t\t\t\t\t       nl_combi,\n\t\t\t\t\t       iface_combination_policy);\n\t\t\tif (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||\n\t\t\t    !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||\n\t\t\t    !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])\n\t\t\t\tgoto broken_combination;\n\n\t\t\tnla_for_each_nested(nl_limit,\n\t\t\t\t\t    tb_comb[NL80211_IFACE_COMB_LIMITS],\n\t\t\t\t\t    rem_limit) {\n\t\t\t\terr = nla_parse_nested(tb_limit,\n\t\t\t\t\t\t       MAX_NL80211_IFACE_LIMIT,\n\t\t\t\t\t\t       nl_limit,\n\t\t\t\t\t\t       iface_limit_policy);\n\t\t\t\tif (err ||\n\t\t\t\t    !tb_limit[NL80211_IFACE_LIMIT_TYPES])\n\t\t\t\t\tgoto broken_combination;\n\n\t\t\t\tnla_for_each_nested(\n\t\t\t\t\tnl_mode,\n\t\t\t\t\ttb_limit[NL80211_IFACE_LIMIT_TYPES],\n\t\t\t\t\trem_mode) {\n\t\t\t\t\tint ift = nla_type(nl_mode);\n\t\t\t\t\tif (ift == NL80211_IFTYPE_P2P_GO ||\n\t\t\t\t\t    ift == NL80211_IFTYPE_P2P_CLIENT)\n\t\t\t\t\t\tcombination_has_p2p = 1;\n\t\t\t\t\tif (ift == NL80211_IFTYPE_STATION)\n\t\t\t\t\t\tcombination_has_mgd = 1;\n\t\t\t\t}\n\t\t\t\tif (combination_has_p2p && combination_has_mgd)\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (combination_has_p2p && combination_has_mgd) {\n\t\t\t\tp2p_concurrent = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\nbroken_combination:\n\t\t\t;\n\t\t}\n\t}\n\n\tif (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {\n\t\tstruct nlattr *nl_cmd;\n\t\tint i;\n\n\t\tnla_for_each_nested(nl_cmd,\n\t\t\t\t    tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) {\n\t\t\tswitch (nla_get_u32(nl_cmd)) {\n\t\t\tcase NL80211_CMD_AUTHENTICATE:\n\t\t\t\tauth_supported = 1;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_CMD_CONNECT:\n\t\t\t\tconnect_supported = 1;\n\t\t\t\tbreak;\n\t\t\tcase NL80211_CMD_START_SCHED_SCAN:\n\t\t\t\t/*\n\t\t\t\t * Disabled for 1.x for now as it is\n\t\t\t\t * broken there due to the way it ends\n\t\t\t\t * up getting used.\n\t\t\t\tcapa->sched_scan_supported = 1;\n\t\t\t\t */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Using driver-based \"\n\t\t\t   \"off-channel TX\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;\n\t}\n\n\tif (tb[NL80211_ATTR_ROAM_SUPPORT]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Using driver-based roaming\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;\n\t}\n\n\t/* default to 5000 since early versions of mac80211 don't set it */\n\tcapa->max_remain_on_chan = 5000;\n\n\tif (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION])\n\t\tcapa->max_remain_on_chan =\n\t\t\tnla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);\n\n\tif (auth_supported)\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_SME;\n\telse if (!connect_supported) {\n\t\twpa_printf(MSG_INFO, \"capwap: Driver does not support \"\n\t\t\t   \"authentication/association or connect commands\");\n\t\tinfo->error = 1;\n\t}\n\n\tif (p2p_go_supported && p2p_client_supported)\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;\n\tif (p2p_concurrent) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Use separate P2P group \"\n\t\t\t   \"interface (driver advertised support)\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;\n\t}\n\n\tif (tb[NL80211_ATTR_TDLS_SUPPORT]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS supported\");\n\t\tcapa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;\n\n\t\tif (tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: TDLS external setup\");\n\t\t\tcapa->flags |=\n\t\t\t\tWPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;\n\t\t}\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int wpa_driver_capwap_get_info(struct wpa_driver_capwap_data *drv,\n\t\t\t\t       struct wiphy_info_data *info)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t\t\t1.wpa_driver_capwap_get_info\");\n\n\tstruct nl_msg *msg;\n\n\tos_memset(info, 0, sizeof(*info));\n\tinfo->capa = &drv->capa;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex);\n\n\tif (send_and_recv_msgs(drv, msg, wiphy_info_handler, info) == 0)\n\t\treturn 0;\n\tmsg = NULL;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int wpa_driver_capwap_capa(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t\t4.wpa_driver_capwap_capa\");\n\tstruct wiphy_info_data info;\n\tif (wpa_driver_capwap_get_info(drv, &info))\n\t\treturn -1;\n\n\tif (info.error)\n\t\treturn -1;\n\n\tdrv->has_capability = 1;\n\t/* For now, assume TKIP, CCMP, WPA, WPA2 are supported */\n\tdrv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |\n\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |\n\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA2 |\n\t\tWPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;\n\tdrv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |\n\t\tWPA_DRIVER_CAPA_ENC_WEP104 |\n\t\tWPA_DRIVER_CAPA_ENC_TKIP |\n\t\tWPA_DRIVER_CAPA_ENC_CCMP;\n\tdrv->capa.auth = WPA_DRIVER_AUTH_OPEN |\n\t\tWPA_DRIVER_AUTH_SHARED |\n\t\tWPA_DRIVER_AUTH_LEAP;\n\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;\n\tdrv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;\n\twpa_printf(MSG_DEBUG, \"1>> drv->capa.flags %d\",drv->capa.flags);\n\twpa_printf(MSG_DEBUG, \"2>> drv->capa.auth  %d\",drv->capa.auth );\n\twpa_printf(MSG_DEBUG, \"2>> drv->capa.enc   %d\",drv->capa.enc  );\n\treturn 0;\n}\n\n\n#ifdef ANDROID\nstatic int android_genl_ctrl_resolve(struct nl_handle *handle,\n\t\t\t\t     const char *name)\n{\n\t/*\n\t * Android ICS has very minimal genl_ctrl_resolve() implementation, so\n\t * need to work around that.\n\t */\n\tstruct nl_cache *cache = NULL;\n\tstruct genl_family *capwap = NULL;\n\tint id = -1;\n\n\tif (genl_ctrl_alloc_cache(handle, &cache) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate generic \"\n\t\t\t   \"netlink cache\");\n\t\tgoto fail;\n\t}\n\n\tcapwap = genl_ctrl_search_by_name(cache, name);\n\tif (capwap == NULL)\n\t\tgoto fail;\n\n\tid = genl_family_get_id(capwap);\n\nfail:\n\tif (capwap)\n\t\tgenl_family_put(capwap);\n\tif (cache)\n\t\tnl_cache_free(cache);\n\n\treturn id;\n}\n#define genl_ctrl_resolve android_genl_ctrl_resolve\n#endif /* ANDROID */\n\n\nstatic int wpa_driver_capwap_init_nl_global(struct capwap_global *global)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t2.wpa_driver_capwap_init_nl_global\\n\");\n\tglobal->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);\n\tif (global->nl_cb == NULL) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to allocate netlink \"\n\t\t\t   \"callbacks\");\n\t\treturn -1;\n\t}\n\n\tif (nl_create_handles(&global->nl, global->nl_cb, \"nl\"))\n\t\treturn -1;\n\n\tglobal->capwap = genl_ctrl_search_by_name(global->nl.cache,\n\t\t\t\t\t\t   \"nl80211\");\n\tif (global->capwap == NULL) {\n\t\twpa_printf(MSG_ERROR, \"capwap: 'capwap' generic netlink not \"\n\t\t\t   \"found\");\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_init_nl(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t1.wpa_driver_capwap_init_nl\\n\");\n\tstruct capwap_global *global = drv->global;\n\tint ret;\n\n\t/* Initialize generic netlink and capwap */\n\n\tif (nl_create_handles(&drv->nl_event, global->nl_cb, \"event\"))\n\t\tgoto err3;\n\n\tret = nl_get_multicast_id(drv, \"nl80211\", \"scan\");\n\tif (ret >= 0)\n\t\tret = nl_socket_add_membership(drv->nl_event.handle, ret);\n\tif (ret < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Could not add multicast \"\n\t\t\t   \"membership for scan events: %d (%s)\",\n\t\t\t   ret, strerror(-ret));\n\t\tgoto err4;\n\t}\n\n\tret = nl_get_multicast_id(drv, \"nl80211\", \"mlme\");\n\tif (ret >= 0)\n\t\tret = nl_socket_add_membership(drv->nl_event.handle, ret);\n\tif (ret < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Could not add multicast \"\n\t\t\t   \"membership for mlme events: %d (%s)\",\n\t\t\t   ret, strerror(-ret));\n\t\tgoto err4;\n\t}\n\n\tret = nl_get_multicast_id(drv, \"nl80211\", \"regulatory\");\n\tif (ret >= 0)\n\t\tret = nl_socket_add_membership(drv->nl_event.handle, ret);\n\tif (ret < 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Could not add multicast \"\n\t\t\t   \"membership for regulatory events: %d (%s)\",\n\t\t\t   ret, strerror(-ret));\n\t\t/* Continue without regulatory events */\n\t}\n\n\teloop_register_read_sock(nl_socket_get_fd(drv->nl_event.handle),\n\t\t\t\t wpa_driver_capwap_event_receive, drv,\n\t\t\t\t drv->nl_event.handle);\n\n\treturn 0;\n\nerr4:\n\tnl_destroy_handles(&drv->nl_event);\nerr3:\n\treturn -1;\n}\n\n\nstatic void wpa_driver_capwap_rfkill_blocked(void *ctx)\n{\n\twpa_printf(MSG_DEBUG, \"capwap: RFKILL blocked\");\n\t/*\n\t * This may be for any interface; use ifdown event to disable\n\t * interface.\n\t */\n}\n\n\nstatic void wpa_driver_capwap_rfkill_unblocked(void *ctx)\n{\n\tstruct wpa_driver_capwap_data *drv = ctx;\n\twpa_printf(MSG_DEBUG, \"capwap: RFKILL unblocked\");\n\tif (linux_set_iface_flags(drv->global->ioctl_sock,\n\t\t\t\t  drv->first_bss.ifname, 1)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Could not set interface UP \"\n\t\t\t   \"after rfkill unblock\");\n\t\treturn;\n\t}\n\t/* rtnetlink ifup handler will report interface as enabled */\n}\n\n\nstatic void capwap_get_phy_name(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t2.capwap_get_phy_name\\n\");\n\n\t/* Find phy (radio) to which this interface belongs */\n\tchar buf[90], *pos;\n\tint f, rv;\n\n\tdrv->phyname[0] = '\\0';\n\tsnprintf(buf, sizeof(buf) - 1, \"/sys/class/net/%s/phy80211/name\",\n\t\t drv->first_bss.ifname);\n\tf = open(buf, O_RDONLY);\n\tif (f < 0) {\n\t\twpa_printf(MSG_DEBUG, \"Could not open file %s: %s\",\n\t\t\t   buf, strerror(errno));\n\t\treturn;\n\t}\n\n\trv = read(f, drv->phyname, sizeof(drv->phyname) - 1);\n\tclose(f);\n\tif (rv < 0) {\n\t\twpa_printf(MSG_DEBUG, \"Could not read file %s: %s\",\n\t\t\t   buf, strerror(errno));\n\t\treturn;\n\t}\n\n\tdrv->phyname[rv] = '\\0';\n\tpos = os_strchr(drv->phyname, '\\n');\n\tif (pos)\n\t\t*pos = '\\0';\n\twpa_printf(MSG_DEBUG, \"capwap: interface %s in phy %s\",\n\t\t   drv->first_bss.ifname, drv->phyname);\n}\n\n\n#ifdef CONFIG_AP\nstatic void capwap_l2_read(void *ctx, const u8 *src_addr, const u8 *buf,\n\t\t\t    size_t len)\n{\n\twpa_printf(MSG_DEBUG, \"capwap: l2_packet read %u\",\n\t\t   (unsigned int) len);\n}\n#endif /* CONFIG_AP */\n\n\n/**\n * wpa_driver_capwap_init - Initialize capwap driver interface\n * @ctx: context to be used when calling wpa_supplicant functions,\n * e.g., wpa_supplicant_event()\n * @ifname: interface name, e.g., wlan0\n * @global_priv: private driver global data from global_init()\n * Returns: Pointer to private data, %NULL on failure\n */\nstatic void * wpa_driver_capwap_init(void *ctx, const char *ifname,\n\t\t\t\t      void *global_priv)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t1.wpa_driver_capwap_init\\n\");\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct rfkill_config *rcfg;\n\tstruct i802_bss *bss;\n\n\tif (global_priv == NULL)\n\t\treturn NULL;\n\tdrv = os_zalloc(sizeof(*drv));\n\tif (drv == NULL)\n\t\treturn NULL;\n\tdrv->global = global_priv;\n\tdrv->ctx = ctx;\n\tbss = &drv->first_bss;\n\tbss->drv = drv;\n\tos_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));\n\tdrv->monitor_ifidx = -1;\n\tdrv->monitor_sock = -1;\n\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n\n\tif (wpa_driver_capwap_init_nl(drv)) {\n\t\tos_free(drv);\n\t\treturn NULL;\n\t}\n\n\tcapwap_get_phy_name(drv);\n\n\trcfg = os_zalloc(sizeof(*rcfg));\n\tif (rcfg == NULL)\n\t\tgoto failed;\n\trcfg->ctx = drv;\n\tos_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));\n\trcfg->blocked_cb = wpa_driver_capwap_rfkill_blocked;\n\trcfg->unblocked_cb = wpa_driver_capwap_rfkill_unblocked;\n\tdrv->rfkill = rfkill_init(rcfg);\n\tif (drv->rfkill == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: RFKILL status not available\");\n\t\tos_free(rcfg);\n\t}\n\n\tif (wpa_driver_capwap_finish_drv_init(drv))\n\t\tgoto failed;\n\n#ifdef CONFIG_AP\n\tdrv->l2 = l2_packet_init(ifname, NULL, ETH_P_EAPOL,\n\t\t\t\t capwap_l2_read, drv, 0);\n#endif /* CONFIG_AP */\n\n\tif (drv->global) {\n\t\tdl_list_add(&drv->global->interfaces, &drv->list);\n\t\tdrv->in_interface_list = 1;\n\t}\n\n\treturn bss;\n\nfailed:\n\twpa_driver_capwap_deinit(bss);\n\treturn NULL;\n}\n\n\nstatic int capwap_register_frame(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct nl_handle *nl_handle,\n\t\t\t\t  u16 type, const u8 *match, size_t match_len)\n{\n\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);\n\tNLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);\n\n\tret = send_and_recv(drv, nl_handle, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Register frame command \"\n\t\t\t   \"failed (type=%u): ret=%d (%s)\",\n\t\t\t   type, ret, strerror(-ret));\n\t\twpa_hexdump(MSG_DEBUG, \"capwap: Register frame match\",\n\t\t\t    match, match_len);\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int capwap_register_action_frame(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t const u8 *match, size_t match_len)\n{\n\tu16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);\n\treturn capwap_register_frame(drv, drv->nl_event.handle,\n\t\t\t\t      type, match, match_len);\n}\n\n\nstatic int capwap_register_action_frames(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t\t6.capwap_register_action_frames\\n\");\n#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)\n\t/* GAS Initial Request */\n\tif (capwap_register_action_frame(drv, (u8 *) \"\\x04\\x0a\", 2) < 0)\n\t\treturn -1;\n\t/* GAS Initial Response */\n\tif (capwap_register_action_frame(drv, (u8 *) \"\\x04\\x0b\", 2) < 0)\n\t\treturn -1;\n\t/* GAS Comeback Request */\n\tif (capwap_register_action_frame(drv, (u8 *) \"\\x04\\x0c\", 2) < 0)\n\t\treturn -1;\n\t/* GAS Comeback Response */\n\tif (capwap_register_action_frame(drv, (u8 *) \"\\x04\\x0d\", 2) < 0)\n\t\treturn -1;\n#endif /* CONFIG_P2P || CONFIG_INTERWORKING */\n#ifdef CONFIG_P2P\n\t/* P2P Public Action */\n\tif (capwap_register_action_frame(drv,\n\t\t\t\t\t  (u8 *) \"\\x04\\x09\\x50\\x6f\\x9a\\x09\",\n\t\t\t\t\t  6) < 0)\n\t\treturn -1;\n\t/* P2P Action */\n\tif (capwap_register_action_frame(drv,\n\t\t\t\t\t  (u8 *) \"\\x7f\\x50\\x6f\\x9a\\x09\",\n\t\t\t\t\t  5) < 0)\n\t\treturn -1;\n#endif /* CONFIG_P2P */\n#ifdef CONFIG_IEEE80211W\n\t/* SA Query Response */\n\tif (capwap_register_action_frame(drv, (u8 *) \"\\x08\\x01\", 2) < 0)\n\t\treturn -1;\n#endif /* CONFIG_IEEE80211W */\n#ifdef CONFIG_TDLS\n\tif ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {\n\t\t/* TDLS Discovery Response */\n\t\tif (capwap_register_action_frame(drv, (u8 *) \"\\x04\\x0e\", 2) <\n\t\t    0)\n\t\t\treturn -1;\n\t}\n#endif /* CONFIG_TDLS */\n\n\t/* FT Action frames */\n\tif (capwap_register_action_frame(drv, (u8 *) \"\\x06\", 1) < 0)\n\t\treturn -1;\n\telse\n\t\tdrv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |\n\t\t\tWPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;\n\n\t/* WNM - BSS Transition Management Request */\n\tif (capwap_register_action_frame(drv, (u8 *) \"\\x0a\\x07\", 2) < 0)\n\t\treturn -1;\n\n\treturn 0;\n}\n\n\nstatic void wpa_driver_capwap_send_rfkill(void *eloop_ctx, void *timeout_ctx)\n{\n\twpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);\n}\n\n\nstatic int\nwpa_driver_capwap_finish_drv_init(struct wpa_driver_capwap_data *drv)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t3.wpa_driver_capwap_finish_drv_init\\n\");\n\n\tstruct i802_bss *bss = &drv->first_bss;\n\tint send_rfkill_event = 0;\n\n\n\tdrv->ifindex = if_nametoindex(bss->ifname);\n\tdrv->first_bss.ifindex = drv->ifindex;\n\n#ifndef HOSTAPD\n\n\t/*\n\t * Make sure the interface starts up in station mode unless this is a\n\t * dynamically added interface (e.g., P2P) that was already configured\n\t * with proper iftype.\n\t */\n\tif (drv->ifindex != drv->global->if_add_ifindex &&\n\t    wpa_driver_capwap_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Could not configure driver to \"\n\t\t\t   \"use managed mode\");\n\t\treturn -1;\n\t}\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {\n\t\tif (rfkill_is_blocked(drv->rfkill)) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Could not yet enable \"\n\t\t\t\t   \"interface '%s' due to rfkill\",\n\t\t\t\t   bss->ifname);\n\t\t\tdrv->if_disabled = 1;\n\t\t\tsend_rfkill_event = 1;\n\t\t} else {\n\t\t\twpa_printf(MSG_ERROR, \"capwap: Could not set \"\n\t\t\t\t   \"interface '%s' UP\", bss->ifname);\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,\n\t\t\t       1, IF_OPER_DORMANT);\n\n#endif /* HOSTAPD */\n\n\tif (wpa_driver_capwap_capa(drv))\n\t\treturn -1;\n\n\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t       drv->addr))\n\t\treturn -1;\n\n\tmemcpy(generic_wtp_info.own_mac_addr,drv->addr,ETH_ALEN);\n\n\tif (capwap_register_action_frames(drv) < 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to register Action \"\n\t\t\t   \"frame processing - ignore for now\");\n\t\t/*\n\t\t * Older kernel versions did not support this, so ignore the\n\t\t * error for now. Some functionality may not be available\n\t\t * because of this.\n\t\t */\n\t}\n\n\tif (send_rfkill_event) {\n\t\teloop_register_timeout(0, 0, wpa_driver_capwap_send_rfkill,\n\t\t\t\t       drv, drv->ctx);\n\t}\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_del_beacon(struct wpa_driver_capwap_data *drv)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\n/**\n * wpa_driver_capwap_deinit - Deinitialize capwap driver interface\n * @priv: Pointer to private capwap data from wpa_driver_capwap_init()\n *\n * Shut down driver interface and processing of driver events. Free\n * private data buffer if one was allocated in wpa_driver_capwap_init().\n */\nstatic void wpa_driver_capwap_deinit(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n#ifdef CONFIG_AP\n\tif (drv->l2)\n\t\tl2_packet_deinit(drv->l2);\n#endif /* CONFIG_AP */\n\n\tif (drv->nl_preq.handle)\n\t\twpa_driver_capwap_probe_req_report(bss, 0);\n\tif (bss->added_if_into_bridge) {\n\t\tif (linux_br_del_if(drv->global->ioctl_sock, bss->brname,\n\t\t\t\t    bss->ifname) < 0)\n\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n\t\t\t\t   \"interface %s from bridge %s: %s\",\n\t\t\t\t   bss->ifname, bss->brname, strerror(errno));\n\t}\n\n\tif (bss->added_bridge) {\n\t\tif (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)\n\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n\t\t\t\t   \"bridge %s: %s\",\n\t\t\t\t   bss->brname, strerror(errno));\n\t}\n\n\tcapwap_remove_monitor_interface(drv);\n\n\tif (is_ap_interface(drv->nlmode))\n\t\twpa_driver_capwap_del_beacon(drv);\n\n#ifdef HOSTAPD\n\tif (drv->last_freq_ht) {\n\t\t/* Clear HT flags from the driver */\n\t\tstruct hostapd_freq_params freq;\n\t\tos_memset(&freq, 0, sizeof(freq));\n\t\tfreq.freq = drv->last_freq;\n\t\ti802_set_freq(priv, &freq);\n\t}\n\n\tif (drv->eapol_sock >= 0) {\n\t\teloop_unregister_read_sock(drv->eapol_sock);\n\t\tclose(drv->eapol_sock);\n\t}\n\n\tif (drv->if_indices != drv->default_if_indices)\n\t\tos_free(drv->if_indices);\n#endif /* HOSTAPD */\n\n\tif (drv->disabled_11b_rates)\n\t\tcapwap_disable_11b_rates(drv, drv->ifindex, 0);\n\n\tnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,\n\t\t\t       IF_OPER_UP);\n\trfkill_deinit(drv->rfkill);\n\n\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv, drv->ctx);\n\n\t(void) linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);\n\twpa_driver_capwap_set_mode(bss, NL80211_IFTYPE_STATION);\n\n\teloop_unregister_read_sock(nl_socket_get_fd(drv->nl_event.handle));\n\tnl_destroy_handles(&drv->nl_event);\n\n\tos_free(drv->filter_ssids);\n\n\tif (drv->in_interface_list)\n\t\tdl_list_del(&drv->list);\n\n\tos_free(drv);\n}\n\n\n/**\n * wpa_driver_capwap_scan_timeout - Scan timeout to report scan completion\n * @eloop_ctx: Driver private data\n * @timeout_ctx: ctx argument given to wpa_driver_capwap_init()\n *\n * This function can be used as registered timeout when starting a scan to\n * generate a scan completed event if the driver does not report this.\n */\nstatic void wpa_driver_capwap_scan_timeout(void *eloop_ctx, void *timeout_ctx)\n{\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\tif (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {\n\t\twpa_driver_capwap_set_mode(&drv->first_bss,\n\t\t\t\t\t    drv->ap_scan_as_station);\n\t\tdrv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;\n\t}\n\twpa_printf(MSG_DEBUG, \"Scan timeout - try to get results\");\n\twpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);\n}\n\n\n/**\n * wpa_driver_capwap_scan - Request the driver to initiate scan\n * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n * @params: Scan parameters\n * Returns: 0 on success, -1 on failure\n */\nstatic int wpa_driver_capwap_scan(void *priv,\n\t\t\t\t   struct wpa_driver_scan_params *params)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = 0, timeout;\n\tstruct nl_msg *msg, *ssids, *freqs, *rates;\n\tsize_t i;\n\n\tmsg = nlmsg_alloc();\n\tssids = nlmsg_alloc();\n\tfreqs = nlmsg_alloc();\n\trates = nlmsg_alloc();\n\tif (!msg || !ssids || !freqs || !rates) {\n\t\tnlmsg_free(msg);\n\t\tnlmsg_free(ssids);\n\t\tnlmsg_free(freqs);\n\t\tnlmsg_free(rates);\n\t\treturn -1;\n\t}\n\n\tos_free(drv->filter_ssids);\n\tdrv->filter_ssids = params->filter_ssids;\n\tparams->filter_ssids = NULL;\n\tdrv->num_filter_ssids = params->num_filter_ssids;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TRIGGER_SCAN);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Scan SSID\",\n\t\t\t\t  ac_params.ssid,\n\t\t\t\t  ac_params.ssid_len);\n\t\tNLA_PUT(ssids, 1, ac_params.ssid_len,\n\t\t\tac_params.ssid);\n\n\n\tfor (i = 1; i < params->num_ssids; i++) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Scan SSID\",\n\t\t\t\t  params->ssids[i].ssid,\n\t\t\t\t  params->ssids[i].ssid_len);\n\t\tNLA_PUT(ssids, i + 1, params->ssids[i].ssid_len,\n\t\t\tparams->ssids[i].ssid);\n\t}\n\tif (params->num_ssids)\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);\n\n\tif (params->extra_ies) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Scan extra IEs\",\n\t\t\t\t  params->extra_ies, params->extra_ies_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,\n\t\t\tparams->extra_ies);\n\t}\n\n\tif (params->freqs) {\n\t\tfor (i = 0; params->freqs[i]; i++) {\n\t\t\twpa_printf(MSG_MSGDUMP, \"capwap: Scan frequency %u \"\n\t\t\t\t   \"MHz\", params->freqs[i]);\n\t\t\tNLA_PUT_U32(freqs, i + 1, params->freqs[i]);\n\t\t}\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);\n\t}\n\n\tif (params->p2p_probe) {\n\t\t/*\n\t\t * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates\n\t\t * by masking out everything else apart from the OFDM rates 6,\n\t\t * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz\n\t\t * rates are left enabled.\n\t\t */\n\t\tNLA_PUT(rates, NL80211_BAND_2GHZ, 8,\n\t\t\t\"\\x0c\\x12\\x18\\x24\\x30\\x48\\x60\\x6c\");\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates);\n\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Scan trigger failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n#ifdef HOSTAPD\n\t\tif (is_ap_interface(drv->nlmode)) {\n\t\t\t/*\n\t\t\t * mac80211 does not allow scan requests in AP mode, so\n\t\t\t * try to do this in station mode.\n\t\t\t */\n\t\t\tif (wpa_driver_capwap_set_mode(\n\t\t\t\t    bss, NL80211_IFTYPE_STATION))\n\t\t\t\tgoto nla_put_failure;\n\n\t\t\tif (wpa_driver_capwap_scan(drv, params)) {\n\t\t\t\twpa_driver_capwap_set_mode(bss, drv->nlmode);\n\t\t\t\tgoto nla_put_failure;\n\t\t\t}\n\n\t\t\t/* Restore AP mode when processing scan results */\n\t\t\tdrv->ap_scan_as_station = drv->nlmode;\n\t\t\tret = 0;\n\t\t} else\n\t\t\tgoto nla_put_failure;\n#else /* HOSTAPD */\n\t\tgoto nla_put_failure;\n#endif /* HOSTAPD */\n\t}\n\n\t/* Not all drivers generate \"scan completed\" wireless event, so try to\n\t * read results after a timeout. */\n\ttimeout = 10;\n\tif (drv->scan_complete_events) {\n\t\t/*\n\t\t * The driver seems to deliver events to notify when scan is\n\t\t * complete, so use longer timeout to avoid race conditions\n\t\t * with scanning and following association request.\n\t\t */\n\t\ttimeout = 30;\n\t}\n\twpa_printf(MSG_DEBUG, \"Scan requested (ret=%d) - scan timeout %d \"\n\t\t   \"seconds\", ret, timeout);\n\teloop_cancel_timeout(wpa_driver_capwap_scan_timeout, drv, drv->ctx);\n\teloop_register_timeout(timeout, 0, wpa_driver_capwap_scan_timeout,\n\t\t\t       drv, drv->ctx);\n\nnla_put_failure:\n\tnlmsg_free(ssids);\n\tnlmsg_free(msg);\n\tnlmsg_free(freqs);\n\tnlmsg_free(rates);\n\treturn ret;\n}\n\n\n/**\n * wpa_driver_capwap_sched_scan - Initiate a scheduled scan\n * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n * @params: Scan parameters\n * @interval: Interval between scan cycles in milliseconds\n * Returns: 0 on success, -1 on failure or if not supported\n */\nstatic int wpa_driver_capwap_sched_scan(void *priv,\n\t\t\t\t\t struct wpa_driver_scan_params *params,\n\t\t\t\t\t u32 interval)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = 0;\n\tstruct nl_msg *msg, *ssids, *freqs, *match_set_ssid, *match_sets;\n\tsize_t i;\n\n\tmsg = nlmsg_alloc();\n\tssids = nlmsg_alloc();\n\tfreqs = nlmsg_alloc();\n\tif (!msg || !ssids || !freqs) {\n\t\tnlmsg_free(msg);\n\t\tnlmsg_free(ssids);\n\t\tnlmsg_free(freqs);\n\t\treturn -1;\n\t}\n\n\tos_free(drv->filter_ssids);\n\tdrv->filter_ssids = params->filter_ssids;\n\tparams->filter_ssids = NULL;\n\tdrv->num_filter_ssids = params->num_filter_ssids;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_START_SCHED_SCAN);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);\n\n\tif (drv->num_filter_ssids) {\n\t\tmatch_sets = nlmsg_alloc();\n\n\t\tfor (i = 0; i < drv->num_filter_ssids; i++) {\n\t\t\twpa_hexdump_ascii(MSG_MSGDUMP,\n\t\t\t\t\t  \"capwap: Sched scan filter SSID\",\n\t\t\t\t\t  drv->filter_ssids[i].ssid,\n\t\t\t\t\t  drv->filter_ssids[i].ssid_len);\n\n\t\t\tmatch_set_ssid = nlmsg_alloc();\n\t\t\tnla_put(match_set_ssid,\n\t\t\t\tNL80211_ATTR_SCHED_SCAN_MATCH_SSID,\n\t\t\t\tdrv->filter_ssids[i].ssid_len,\n\t\t\t\tdrv->filter_ssids[i].ssid);\n\n\t\t\tnla_put_nested(match_sets, i + 1, match_set_ssid);\n\n\t\t\tnlmsg_free(match_set_ssid);\n\t\t}\n\n\t\tnla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,\n\t\t\t       match_sets);\n\t\tnlmsg_free(match_sets);\n\t}\n\n\n\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Sched scan SSID\",\n\t\t\t\t  ac_params.ssid,\n\t\t\t\t  ac_params.ssid_len);\n\tNLA_PUT(ssids,   1, ac_params.ssid_len,\tac_params.ssid);\n\n\n\tfor (i = 1; i < params->num_ssids; i++) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Sched scan SSID\",\n\t\t\t\t  params->ssids[i].ssid,\n\t\t\t\t  params->ssids[i].ssid_len);\n\t\tNLA_PUT(ssids, i + 1, params->ssids[i].ssid_len,\n\t\t\tparams->ssids[i].ssid);\n\t}\n\tif (params->num_ssids)\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);\n\n\tif (params->extra_ies) {\n\t\twpa_hexdump_ascii(MSG_MSGDUMP, \"capwap: Sched scan extra IEs\",\n\t\t\t\t  params->extra_ies, params->extra_ies_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,\n\t\t\tparams->extra_ies);\n\t}\n\n\tif (params->freqs) {\n\t\tfor (i = 0; params->freqs[i]; i++) {\n\t\t\twpa_printf(MSG_MSGDUMP, \"capwap: Scan frequency %u \"\n\t\t\t\t   \"MHz\", params->freqs[i]);\n\t\t\tNLA_PUT_U32(freqs, i + 1, params->freqs[i]);\n\t\t}\n\t\tnla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\n\t/* TODO: if we get an error here, we should fall back to normal scan */\n\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan start failed: \"\n\t\t\t   \"ret=%d (%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Sched scan requested (ret=%d) - \"\n\t\t   \"scan interval %d msec\", ret, interval);\n\nnla_put_failure:\n\tnlmsg_free(ssids);\n\tnlmsg_free(msg);\n\tnlmsg_free(freqs);\n\treturn ret;\n}\n\n\n/**\n * wpa_driver_capwap_stop_sched_scan - Stop a scheduled scan\n * @priv: Pointer to private driver data from wpa_driver_capwap_init()\n * Returns: 0 on success, -1 on failure or if not supported\n */\nstatic int wpa_driver_capwap_stop_sched_scan(void *priv)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = 0;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stop failed: \"\n\t\t\t   \"ret=%d (%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Sched scan stop sent (ret=%d)\", ret);\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic const u8 * capwap_get_ie(const u8 *ies, size_t ies_len, u8 ie)\n{\n\tconst u8 *end, *pos;\n\n\tif (ies == NULL)\n\t\treturn NULL;\n\n\tpos = ies;\n\tend = ies + ies_len;\n\n\twhile (pos + 1 < end) {\n\t\tif (pos + 2 + pos[1] > end)\n\t\t\tbreak;\n\t\tif (pos[0] == ie)\n\t\t\treturn pos;\n\t\tpos += 2 + pos[1];\n\t}\n\n\treturn NULL;\n}\n\n\nstatic int capwap_scan_filtered(struct wpa_driver_capwap_data *drv,\n\t\t\t\t const u8 *ie, size_t ie_len)\n{\n\tconst u8 *ssid;\n\tsize_t i;\n\n\tif (drv->filter_ssids == NULL)\n\t\treturn 0;\n\n\tssid = capwap_get_ie(ie, ie_len, WLAN_EID_SSID);\n\tif (ssid == NULL)\n\t\treturn 1;\n\n\tfor (i = 0; i < drv->num_filter_ssids; i++) {\n\t\tif (ssid[1] == drv->filter_ssids[i].ssid_len &&\n\t\t    os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==\n\t\t    0)\n\t\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n\n\nstatic int bss_info_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *bss[NL80211_BSS_MAX + 1];\n\tstatic struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {\n\t\t[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },\n\t\t[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_TSF] = { .type = NLA_U64 },\n\t\t[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },\n\t\t[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },\n\t\t[NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },\n\t\t[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },\n\t\t[NL80211_BSS_STATUS] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },\n\t\t[NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },\n\t};\n\tstruct capwap_bss_info_arg *_arg = arg;\n\tstruct wpa_scan_results *res = _arg->res;\n\tstruct wpa_scan_res **tmp;\n\tstruct wpa_scan_res *r;\n\tconst u8 *ie, *beacon_ie;\n\tsize_t ie_len, beacon_ie_len;\n\tu8 *pos;\n\tsize_t i;\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb[NL80211_ATTR_BSS])\n\t\treturn NL_SKIP;\n\tif (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],\n\t\t\t     bss_policy))\n\t\treturn NL_SKIP;\n\tif (bss[NL80211_BSS_STATUS]) {\n\t\tenum nl80211_bss_status status;\n\t\tstatus = nla_get_u32(bss[NL80211_BSS_STATUS]);\n\t\tif (status == NL80211_BSS_STATUS_ASSOCIATED &&\n\t\t    bss[NL80211_BSS_FREQUENCY]) {\n\t\t\t_arg->assoc_freq =\n\t\t\t\tnla_get_u32(bss[NL80211_BSS_FREQUENCY]);\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Associated on %u MHz\",\n\t\t\t\t   _arg->assoc_freq);\n\t\t}\n\t\tif (status == NL80211_BSS_STATUS_ASSOCIATED &&\n\t\t    bss[NL80211_BSS_BSSID]) {\n\t\t\tos_memcpy(_arg->assoc_bssid,\n\t\t\t\t  nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Associated with \"\n\t\t\t\t   MACSTR, MAC2STR(_arg->assoc_bssid));\n\t\t}\n\t}\n\tif (!res)\n\t\treturn NL_SKIP;\n\tif (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {\n\t\tie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);\n\t\tie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);\n\t} else {\n\t\tie = NULL;\n\t\tie_len = 0;\n\t}\n\tif (bss[NL80211_BSS_BEACON_IES]) {\n\t\tbeacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);\n\t\tbeacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);\n\t} else {\n\t\tbeacon_ie = NULL;\n\t\tbeacon_ie_len = 0;\n\t}\n\n\tif (capwap_scan_filtered(_arg->drv, ie ? ie : beacon_ie,\n\t\t\t\t  ie ? ie_len : beacon_ie_len))\n\t\treturn NL_SKIP;\n\n\tr = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);\n\tif (r == NULL)\n\t\treturn NL_SKIP;\n\tif (bss[NL80211_BSS_BSSID])\n\t\tos_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),\n\t\t\t  ETH_ALEN);\n\tif (bss[NL80211_BSS_FREQUENCY])\n\t\tr->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);\n\tif (bss[NL80211_BSS_BEACON_INTERVAL])\n\t\tr->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);\n\tif (bss[NL80211_BSS_CAPABILITY])\n\t\tr->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);\n\tr->flags |= WPA_SCAN_NOISE_INVALID;\n\tif (bss[NL80211_BSS_SIGNAL_MBM]) {\n\t\tr->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);\n\t\tr->level /= 100; /* mBm to dBm */\n\t\tr->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;\n\t} else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {\n\t\tr->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);\n\t\tr->flags |= WPA_SCAN_QUAL_INVALID;\n\t} else\n\t\tr->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;\n\tif (bss[NL80211_BSS_TSF])\n\t\tr->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);\n\tif (bss[NL80211_BSS_SEEN_MS_AGO])\n\t\tr->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);\n\tr->ie_len = ie_len;\n\tpos = (u8 *) (r + 1);\n\tif (ie) {\n\t\tos_memcpy(pos, ie, ie_len);\n\t\tpos += ie_len;\n\t}\n\tr->beacon_ie_len = beacon_ie_len;\n\tif (beacon_ie)\n\t\tos_memcpy(pos, beacon_ie, beacon_ie_len);\n\n\tif (bss[NL80211_BSS_STATUS]) {\n\t\tenum nl80211_bss_status status;\n\t\tstatus = nla_get_u32(bss[NL80211_BSS_STATUS]);\n\t\tswitch (status) {\n\t\tcase NL80211_BSS_STATUS_AUTHENTICATED:\n\t\t\tr->flags |= WPA_SCAN_AUTHENTICATED;\n\t\t\tbreak;\n\t\tcase NL80211_BSS_STATUS_ASSOCIATED:\n\t\t\tr->flags |= WPA_SCAN_ASSOCIATED;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t * cfg80211 maintains separate BSS table entries for APs if the same\n\t * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does\n\t * not use frequency as a separate key in the BSS table, so filter out\n\t * duplicated entries. Prefer associated BSS entry in such a case in\n\t * order to get the correct frequency into the BSS table.\n\t */\n\tfor (i = 0; i < res->num; i++) {\n\t\tconst u8 *s1, *s2;\n\t\tif (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)\n\t\t\tcontinue;\n\n\t\ts1 = capwap_get_ie((u8 *) (res->res[i] + 1),\n\t\t\t\t    res->res[i]->ie_len, WLAN_EID_SSID);\n\t\ts2 = capwap_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);\n\t\tif (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||\n\t\t    os_memcmp(s1, s2, 2 + s1[1]) != 0)\n\t\t\tcontinue;\n\n\t\t/* Same BSSID,SSID was already included in scan results */\n\t\twpa_printf(MSG_DEBUG, \"capwap: Remove duplicated scan result \"\n\t\t\t   \"for \" MACSTR, MAC2STR(r->bssid));\n\n\t\tif ((r->flags & WPA_SCAN_ASSOCIATED) &&\n\t\t    !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) {\n\t\t\tos_free(res->res[i]);\n\t\t\tres->res[i] = r;\n\t\t} else\n\t\t\tos_free(r);\n\t\treturn NL_SKIP;\n\t}\n\n\ttmp = os_realloc(res->res,\n\t\t\t (res->num + 1) * sizeof(struct wpa_scan_res *));\n\tif (tmp == NULL) {\n\t\tos_free(r);\n\t\treturn NL_SKIP;\n\t}\n\ttmp[res->num++] = r;\n\tres->res = tmp;\n\n\treturn NL_SKIP;\n}\n\n\nstatic void clear_state_mismatch(struct wpa_driver_capwap_data *drv,\n\t\t\t\t const u8 *addr)\n{\n\tif (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Clear possible state \"\n\t\t\t   \"mismatch (\" MACSTR \")\", MAC2STR(addr));\n\t\twpa_driver_capwap_mlme(drv, addr,\n\t\t\t\t\tNL80211_CMD_DEAUTHENTICATE,\n\t\t\t\t\tWLAN_REASON_PREV_AUTH_NOT_VALID, 1);\n\t}\n}\n\n\nstatic void wpa_driver_capwap_check_bss_status(\n\tstruct wpa_driver_capwap_data *drv, struct wpa_scan_results *res)\n{\n\tsize_t i;\n\n\tfor (i = 0; i < res->num; i++) {\n\t\tstruct wpa_scan_res *r = res->res[i];\n\t\tif (r->flags & WPA_SCAN_AUTHENTICATED) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Scan results \"\n\t\t\t\t   \"indicates BSS status with \" MACSTR\n\t\t\t\t   \" as authenticated\",\n\t\t\t\t   MAC2STR(r->bssid));\n\t\t\tif (is_sta_interface(drv->nlmode) &&\n\t\t\t    os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&\n\t\t\t    os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=\n\t\t\t    0) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Unknown BSSID\"\n\t\t\t\t\t   \" in local state (auth=\" MACSTR\n\t\t\t\t\t   \" assoc=\" MACSTR \")\",\n\t\t\t\t\t   MAC2STR(drv->auth_bssid),\n\t\t\t\t\t   MAC2STR(drv->bssid));\n\t\t\t\tclear_state_mismatch(drv, r->bssid);\n\t\t\t}\n\t\t}\n\n\t\tif (r->flags & WPA_SCAN_ASSOCIATED) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Scan results \"\n\t\t\t\t   \"indicate BSS status with \" MACSTR\n\t\t\t\t   \" as associated\",\n\t\t\t\t   MAC2STR(r->bssid));\n\t\t\tif (is_sta_interface(drv->nlmode) &&\n\t\t\t    !drv->associated) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Local state \"\n\t\t\t\t\t   \"(not associated) does not match \"\n\t\t\t\t\t   \"with BSS state\");\n\t\t\t\tclear_state_mismatch(drv, r->bssid);\n\t\t\t} else if (is_sta_interface(drv->nlmode) &&\n\t\t\t\t   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=\n\t\t\t\t   0) {\n\t\t\t\twpa_printf(MSG_DEBUG, \"capwap: Local state \"\n\t\t\t\t\t   \"(associated with \" MACSTR \") does \"\n\t\t\t\t\t   \"not match with BSS state\",\n\t\t\t\t\t   MAC2STR(drv->bssid));\n\t\t\t\tclear_state_mismatch(drv, r->bssid);\n\t\t\t\tclear_state_mismatch(drv, drv->bssid);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nstatic struct wpa_scan_results *\ncapwap_get_scan_results(struct wpa_driver_capwap_data *drv)\n{\n\tstruct nl_msg *msg;\n\tstruct wpa_scan_results *res;\n\tint ret;\n\tstruct capwap_bss_info_arg arg;\n\n\tres = os_zalloc(sizeof(*res));\n\tif (res == NULL)\n\t\treturn NULL;\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\targ.drv = drv;\n\targ.res = res;\n\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Received scan results (%lu \"\n\t\t\t   \"BSSes)\", (unsigned long) res->num);\n\t\tcapwap_get_noise_for_scan_results(drv, res);\n\t\treturn res;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n\t\t   \"(%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_scan_results_free(res);\n\treturn NULL;\n}\n\n\n/**\n * wpa_driver_capwap_get_scan_results - Fetch the latest scan results\n * @priv: Pointer to private wext data from wpa_driver_capwap_init()\n * Returns: Scan results on success, -1 on failure\n */\nstatic struct wpa_scan_results *\nwpa_driver_capwap_get_scan_results(void *priv)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct wpa_scan_results *res;\n\n\tres = capwap_get_scan_results(drv);\n\tif (res)\n\t\twpa_driver_capwap_check_bss_status(drv, res);\n\treturn res;\n}\n\n\nstatic void capwap_dump_scan(struct wpa_driver_capwap_data *drv)\n{\n\tstruct wpa_scan_results *res;\n\tsize_t i;\n\n\tres = capwap_get_scan_results(drv);\n\tif (res == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to get scan results\");\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result dump\");\n\tfor (i = 0; i < res->num; i++) {\n\t\tstruct wpa_scan_res *r = res->res[i];\n\t\twpa_printf(MSG_DEBUG, \"capwap: %d/%d \" MACSTR \"%s%s\",\n\t\t\t   (int) i, (int) res->num, MAC2STR(r->bssid),\n\t\t\t   r->flags & WPA_SCAN_AUTHENTICATED ? \" [auth]\" : \"\",\n\t\t\t   r->flags & WPA_SCAN_ASSOCIATED ? \" [assoc]\" : \"\");\n\t}\n\n\twpa_scan_results_free(res);\n}\n\n\nstatic int wpa_driver_capwap_set_key(const char *ifname, void *priv,\n\t\t\t\t      enum wpa_alg alg, const u8 *addr,\n\t\t\t\t      int key_idx, int set_tx,\n\t\t\t\t      const u8 *seq, size_t seq_len,\n\t\t\t\t      const u8 *key, size_t key_len)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ifindex = if_nametoindex(ifname);\n\tstruct nl_msg *msg;\n\tint ret;\n\n\twpa_printf(MSG_DEBUG, \"%s: ifindex=%d alg=%d addr=%p key_idx=%d \"\n\t\t   \"set_tx=%d seq_len=%lu key_len=%lu\",\n\t\t   __func__, ifindex, alg, addr, key_idx, set_tx,\n\t\t   (unsigned long) seq_len, (unsigned long) key_len);\n#ifdef CONFIG_TDLS\n\tif (key_idx == -1)\n\t\tkey_idx = 0;\n#endif /* CONFIG_TDLS */\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tif (alg == WPA_ALG_NONE) {\n\t\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);\n\t} else {\n\t\tcapwap_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);\n\t\tNLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);\n\t\tswitch (alg) {\n\t\tcase WPA_ALG_WEP:\n\t\t\tif (key_len == 5)\n\t\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\t\telse\n\t\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\t\t\tbreak;\n\t\tcase WPA_ALG_TKIP:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_TKIP);\n\t\t\tbreak;\n\t\tcase WPA_ALG_CCMP:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_CCMP);\n\t\t\tbreak;\n\t\tcase WPA_ALG_IGTK:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_AES_CMAC);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\twpa_printf(MSG_ERROR, \"%s: Unsupported encryption \"\n\t\t\t\t   \"algorithm %d\", __func__, alg);\n\t\t\tnlmsg_free(msg);\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tif (seq && seq_len)\n\t\tNLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);\n\n\tif (addr && !is_broadcast_ether_addr(addr)) {\n\t\twpa_printf(MSG_DEBUG, \"   addr=\" MACSTR, MAC2STR(addr));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\n\t\tif (alg != WPA_ALG_WEP && key_idx && !set_tx) {\n\t\t\twpa_printf(MSG_DEBUG, \"   RSN IBSS RX GTK\");\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE,\n\t\t\t\t    NL80211_KEYTYPE_GROUP);\n\t\t}\n\t} else if (addr && is_broadcast_ether_addr(addr)) {\n\t\tstruct nl_msg *types;\n\t\tint err;\n\t\twpa_printf(MSG_DEBUG, \"   broadcast key\");\n\t\ttypes = nlmsg_alloc();\n\t\tif (!types)\n\t\t\tgoto nla_put_failure;\n\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);\n\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n\t\t\t\t     types);\n\t\tnlmsg_free(types);\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t}\n\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)\n\t\tret = 0;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: set_key failed; err=%d %s)\",\n\t\t\t   ret, strerror(-ret));\n\n\t/*\n\t * If we failed or don't need to set the default TX key (below),\n\t * we're done here.\n\t */\n\tif (ret || !set_tx || alg == WPA_ALG_NONE)\n\t\treturn ret;\n\tif (is_ap_interface(drv->nlmode) && addr &&\n\t    !is_broadcast_ether_addr(addr))\n\t\treturn ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);\n\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\tif (alg == WPA_ALG_IGTK)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT);\n\telse\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);\n\tif (addr && is_broadcast_ether_addr(addr)) {\n\t\tstruct nl_msg *types;\n\t\tint err;\n\t\ttypes = nlmsg_alloc();\n\t\tif (!types)\n\t\t\tgoto nla_put_failure;\n\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);\n\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n\t\t\t\t     types);\n\t\tnlmsg_free(types);\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t} else if (addr) {\n\t\tstruct nl_msg *types;\n\t\tint err;\n\t\ttypes = nlmsg_alloc();\n\t\tif (!types)\n\t\t\tgoto nla_put_failure;\n\t\tNLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST);\n\t\terr = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,\n\t\t\t\t     types);\n\t\tnlmsg_free(types);\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif (ret == -ENOENT)\n\t\tret = 0;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: set_key default failed; \"\n\t\t\t   \"err=%d %s)\", ret, strerror(-ret));\n\treturn ret;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,\n\t\t      int key_idx, int defkey,\n\t\t      const u8 *seq, size_t seq_len,\n\t\t      const u8 *key, size_t key_len)\n{\n\tstruct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);\n\tif (!key_attr)\n\t\treturn -1;\n\n\tif (defkey && alg == WPA_ALG_IGTK)\n\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);\n\telse if (defkey)\n\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);\n\n\tNLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);\n\n\tswitch (alg) {\n\tcase WPA_ALG_WEP:\n\t\tif (key_len == 5)\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\telse\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\t\tbreak;\n\tcase WPA_ALG_TKIP:\n\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP);\n\t\tbreak;\n\tcase WPA_ALG_CCMP:\n\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP);\n\t\tbreak;\n\tcase WPA_ALG_IGTK:\n\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t    WLAN_CIPHER_SUITE_AES_CMAC);\n\t\tbreak;\n\tdefault:\n\t\twpa_printf(MSG_ERROR, \"%s: Unsupported encryption \"\n\t\t\t   \"algorithm %d\", __func__, alg);\n\t\treturn -1;\n\t}\n\n\tif (seq && seq_len)\n\t\tNLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);\n\n\tNLA_PUT(msg, NL80211_KEY_DATA, key_len, key);\n\n\tnla_nest_end(msg, key_attr);\n\n\treturn 0;\n nla_put_failure:\n\treturn -1;\n}\n\n\nstatic int capwap_set_conn_keys(struct wpa_driver_associate_params *params,\n\t\t\t\t struct nl_msg *msg)\n{\n\tint i, privacy = 0;\n\tstruct nlattr *nl_keys, *nl_key;\n\n\tfor (i = 0; i < 4; i++) {\n\t\tif (!params->wep_key[i])\n\t\t\tcontinue;\n\t\tprivacy = 1;\n\t\tbreak;\n\t}\n\tif (params->wps == WPS_MODE_PRIVACY)\n\t\tprivacy = 1;\n\tif (params->pairwise_suite &&\n\t    params->pairwise_suite != WPA_CIPHER_NONE)\n\t\tprivacy = 1;\n\n\tif (!privacy)\n\t\treturn 0;\n\n\tNLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);\n\n\tnl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);\n\tif (!nl_keys)\n\t\tgoto nla_put_failure;\n\n\tfor (i = 0; i < 4; i++) {\n\t\tif (!params->wep_key[i])\n\t\t\tcontinue;\n\n\t\tnl_key = nla_nest_start(msg, i);\n\t\tif (!nl_key)\n\t\t\tgoto nla_put_failure;\n\n\t\tNLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],\n\t\t\tparams->wep_key[i]);\n\t\tif (params->wep_key_len[i] == 5)\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\telse\n\t\t\tNLA_PUT_U32(msg, NL80211_KEY_CIPHER,\n\t\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\n\t\tNLA_PUT_U8(msg, NL80211_KEY_IDX, i);\n\n\t\tif (i == params->wep_tx_keyidx)\n\t\t\tNLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);\n\n\t\tnla_nest_end(msg, nl_key);\n\t}\n\tnla_nest_end(msg, nl_keys);\n\n\treturn 0;\n\nnla_put_failure:\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_mlme(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   const u8 *addr, int cmd, u16 reason_code,\n\t\t\t\t   int local_state_change)\n{\n\n\tint ret = -1;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, cmd);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tif (local_state_change)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME command failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t const u8 *addr, int reason_code)\n{\n\twpa_printf(MSG_DEBUG, \"%s(addr=\" MACSTR \" reason_code=%d)\",\n\t\t   __func__, MAC2STR(addr), reason_code);\n\tdrv->associated = 0;\n\treturn wpa_driver_capwap_mlme(drv, addr, NL80211_CMD_DISCONNECT,\n\t\t\t\t       reason_code, 0);\n}\n\n\nstatic int wpa_driver_capwap_deauthenticate(void *priv, const u8 *addr,\n\t\t\t\t\t     int reason_code)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))\n\t\treturn wpa_driver_capwap_disconnect(drv, addr, reason_code);\n\twpa_printf(MSG_DEBUG, \"%s(addr=\" MACSTR \" reason_code=%d)\",\n\t\t   __func__, MAC2STR(addr), reason_code);\n\tdrv->associated = 0;\n\tif (drv->nlmode == NL80211_IFTYPE_ADHOC)\n\t\treturn capwap_leave_ibss(drv);\n\treturn wpa_driver_capwap_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,\n\t\t\t\t       reason_code, 0);\n}\n\n\nstatic int wpa_driver_capwap_disassociate(void *priv, const u8 *addr,\n\t\t\t\t\t   int reason_code)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))\n\t\treturn wpa_driver_capwap_disconnect(drv, addr, reason_code);\n\twpa_printf(MSG_DEBUG, \"%s\", __func__);\n\tdrv->associated = 0;\n\treturn wpa_driver_capwap_mlme(drv, addr, NL80211_CMD_DISASSOCIATE,\n\t\t\t\t       reason_code, 0);\n}\n\n\nstatic int wpa_driver_capwap_authenticate(\n\tvoid *priv, struct wpa_driver_auth_params *params)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1, i;\n\tstruct nl_msg *msg;\n\tenum nl80211_auth_type type;\n\tenum nl80211_iftype nlmode;\n\tint count = 0;\n\n\tdrv->associated = 0;\n\tos_memset(drv->auth_bssid, 0, ETH_ALEN);\n\t/* FIX: IBSS mode */\n\tnlmode = params->p2p ?\n\t\tNL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;\n\tif (drv->nlmode != nlmode &&\n\t    wpa_driver_capwap_set_mode(priv, nlmode) < 0)\n\t\treturn -1;\n\nretry:\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Authenticate (ifindex=%d)\",\n\t\t   drv->ifindex);\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);\n\n\tfor (i = 0; i < 4; i++) {\n\t\tif (!params->wep_key[i])\n\t\t\tcontinue;\n\t\twpa_driver_capwap_set_key(bss->ifname, priv, WPA_ALG_WEP,\n\t\t\t\t\t   NULL, i,\n\t\t\t\t\t   i == params->wep_tx_keyidx, NULL, 0,\n\t\t\t\t\t   params->wep_key[i],\n\t\t\t\t\t   params->wep_key_len[i]);\n\t\tif (params->wep_tx_keyidx != i)\n\t\t\tcontinue;\n\t\tif (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,\n\t\t\t       params->wep_key[i], params->wep_key_len[i])) {\n\t\t\tnlmsg_free(msg);\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tif (params->bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n\t}\n\tif (params->freq) {\n\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\t}\n\tif (ac_params.ssid) {\n\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t\t  ac_params.ssid, ac_params.ssid_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_SSID, ac_params.ssid_len,\n\t\t\tac_params.ssid);\n\t}\n\n\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->ie, params->ie_len);\n\tif (params->ie)\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie);\n\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n\t\ttype = NL80211_AUTHTYPE_OPEN_SYSTEM;\n\telse if (params->auth_alg & WPA_AUTH_ALG_SHARED)\n\t\ttype = NL80211_AUTHTYPE_SHARED_KEY;\n\telse if (params->auth_alg & WPA_AUTH_ALG_LEAP)\n\t\ttype = NL80211_AUTHTYPE_NETWORK_EAP;\n\telse if (params->auth_alg & WPA_AUTH_ALG_FT)\n\t\ttype = NL80211_AUTHTYPE_FT;\n\telse\n\t\tgoto nla_put_failure;\n\twpa_printf(MSG_DEBUG, \"  * Auth Type %d\", type);\n\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);\n\tif (params->local_state_change) {\n\t\twpa_printf(MSG_DEBUG, \"  * Local state change only\");\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME command failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tcount++;\n\t\tif (ret == -EALREADY && count == 1 && params->bssid &&\n\t\t    !params->local_state_change) {\n\t\t\t/*\n\t\t\t * mac80211 does not currently accept new\n\t\t\t * authentication if we are already authenticated. As a\n\t\t\t * workaround, force deauthentication and try again.\n\t\t\t */\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Retry authentication \"\n\t\t\t\t   \"after forced deauthentication\");\n\t\t\twpa_driver_capwap_deauthenticate(\n\t\t\t\tbss, params->bssid,\n\t\t\t\tWLAN_REASON_PREV_AUTH_NOT_VALID);\n\t\t\tnlmsg_free(msg);\n\t\t\tgoto retry;\n\t\t}\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Authentication request send \"\n\t\t   \"successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstruct phy_info_arg {\n\tu16 *num_modes;\n\tstruct hostapd_hw_modes *modes;\n};\n\nstatic int phy_info_handler(struct nl_msg *msg, void *arg)\n{\n\n\tstruct nlattr *tb_msg[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct phy_info_arg *phy_info = arg;\n\n\tstruct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];\n\n\tstruct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];\n\tstatic struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {\n\t\t[NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },\n\t\t[NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },\n\t\t[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },\n\t};\n\n\tstruct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];\n\tstatic struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {\n\t\t[NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },\n\t\t[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG },\n\t};\n\n\tstruct nlattr *nl_band;\n\tstruct nlattr *nl_freq;\n\tstruct nlattr *nl_rate;\n\tint rem_band, rem_freq, rem_rate;\n\tstruct hostapd_hw_modes *mode;\n\tint idx, mode_is_set;\n\n\tnla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\tif (!tb_msg[NL80211_ATTR_WIPHY_BANDS])\n\t\treturn NL_SKIP;\n\n\tnla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {\n\t\tmode = os_realloc(phy_info->modes, (*phy_info->num_modes + 1) * sizeof(*mode));\n\t\tif (!mode)\n\t\t\treturn NL_SKIP;\n\t\tphy_info->modes = mode;\n\n\t\tmode_is_set = 0;\n\n\t\tmode = &phy_info->modes[*(phy_info->num_modes)];\n\t\tmemset(mode, 0, sizeof(*mode));\n\t\tmode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN;\n\t\t*(phy_info->num_modes) += 1;\n\n\t\tnla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),\n\t\t\t  nla_len(nl_band), NULL);\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {\n\t\t\tmode->ht_capab = nla_get_u16(\n\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_CAPA]);\n\t\t}\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) {\n\t\t\tmode->a_mpdu_params |= nla_get_u8(\n\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) &\n\t\t\t\t0x03;\n\t\t}\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) {\n\t\t\tmode->a_mpdu_params |= nla_get_u8(\n\t\t\t\ttb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) <<\n\t\t\t\t2;\n\t\t}\n\n\t\tif (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] &&\n\t\t    nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])) {\n\t\t\tu8 *mcs;\n\t\t\tmcs = nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);\n\t\t\tos_memcpy(mode->mcs_set, mcs, 16);\n\t\t}\n\n\t\tnla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {\n\t\t\tnla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),\n\t\t\t\t  nla_len(nl_freq), freq_policy);\n\t\t\tif (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])\n\t\t\t\tcontinue;\n\t\t\tmode->num_channels++;\n\t\t}\n\n\t\tmode->channels = os_zalloc(mode->num_channels * sizeof(struct hostapd_channel_data));\n\t\tif (!mode->channels)\n\t\t\treturn NL_SKIP;\n\n\t\tidx = 0;\n\n\t\tnla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {\n\t\t\tnla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),\n\t\t\t\t  nla_len(nl_freq), freq_policy);\n\t\t\tif (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])\n\t\t\t\tcontinue;\n\n\t\t\tmode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);\n\t\t\tmode->channels[idx].flag = 0;\n\n\t\t\tif (!mode_is_set) {\n\t\t\t\t/* crude heuristic */\n\t\t\t\tif (mode->channels[idx].freq < 4000)\n\t\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n\t\t\t\telse\n\t\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211A;\n\t\t\t\tmode_is_set = 1;\n\t\t\t}\n\n\t\t\t/* crude heuristic */\n\t\t\tif (mode->channels[idx].freq < 4000)\n\t\t\t\tif (mode->channels[idx].freq == 2484)\n\t\t\t\t\tmode->channels[idx].chan = 14;\n\t\t\t\telse\n\t\t\t\t\tmode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5;\n\t\t\telse\n\t\t\t\tmode->channels[idx].chan = mode->channels[idx].freq/5 - 1000;\n\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_DISABLED;\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_PASSIVE_SCAN;\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_NO_IBSS;\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])\n\t\t\t\tmode->channels[idx].flag |=\n\t\t\t\t\tHOSTAPD_CHAN_RADAR;\n\n\t\t\tif (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] &&\n\t\t\t    !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])\n\t\t\t\tmode->channels[idx].max_tx_power =\n\t\t\t\t\tnla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100;\n\n\t\t\tidx++;\n\t\t}\n\n\t\tnla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {\n\t\t\tnla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),\n\t\t\t\t  nla_len(nl_rate), rate_policy);\n\t\t\tif (!tb_rate[NL80211_BITRATE_ATTR_RATE])\n\t\t\t\tcontinue;\n\t\t\tmode->num_rates++;\n\t\t}\n\n\t\tmode->rates = os_zalloc(mode->num_rates * sizeof(int));\n\t\tif (!mode->rates)\n\t\t\treturn NL_SKIP;\n\n\t\tidx = 0;\n\n\t\tnla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {\n\t\t\tnla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),\n\t\t\t\t  nla_len(nl_rate), rate_policy);\n\t\t\tif (!tb_rate[NL80211_BITRATE_ATTR_RATE])\n\t\t\t\tcontinue;\n\t\t\tmode->rates[idx] = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]);\n\n\t\t\t/* crude heuristic */\n\t\t\tif (mode->mode == HOSTAPD_MODE_IEEE80211B &&\n\t\t\t    mode->rates[idx] > 200)\n\t\t\t\tmode->mode = HOSTAPD_MODE_IEEE80211G;\n\n\t\t\tidx++;\n\t\t}\n\t}\n\n\treturn NL_SKIP;\n}\n\nstatic struct hostapd_hw_modes *\nwpa_driver_capwap_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes)\n{\n\tu16 m;\n\tstruct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;\n\tint i, mode11g_idx = -1;\n\n\t/* If only 802.11g mode is included, use it to construct matching\n\t * 802.11b mode data. */\n\n\tfor (m = 0; m < *num_modes; m++) {\n\t\tif (modes[m].mode == HOSTAPD_MODE_IEEE80211B)\n\t\t\treturn modes; /* 802.11b already included */\n\t\tif (modes[m].mode == HOSTAPD_MODE_IEEE80211G)\n\t\t\tmode11g_idx = m;\n\t}\n\n\tif (mode11g_idx < 0)\n\t\treturn modes; /* 2.4 GHz band not supported at all */\n\n\tnmodes = os_realloc(modes, (*num_modes + 1) * sizeof(*nmodes));\n\tif (nmodes == NULL)\n\t\treturn modes; /* Could not add 802.11b mode */\n\n\tmode = &nmodes[*num_modes];\n\tos_memset(mode, 0, sizeof(*mode));\n\t(*num_modes)++;\n\tmodes = nmodes;\n\n\tmode->mode = HOSTAPD_MODE_IEEE80211B;\n\n\tmode11g = &modes[mode11g_idx];\n\tmode->num_channels = mode11g->num_channels;\n\tmode->channels = os_malloc(mode11g->num_channels *\n\t\t\t\t   sizeof(struct hostapd_channel_data));\n\tif (mode->channels == NULL) {\n\t\t(*num_modes)--;\n\t\treturn modes; /* Could not add 802.11b mode */\n\t}\n\tos_memcpy(mode->channels, mode11g->channels,\n\t\t  mode11g->num_channels * sizeof(struct hostapd_channel_data));\n\n\tmode->num_rates = 0;\n\tmode->rates = os_malloc(4 * sizeof(int));\n\tif (mode->rates == NULL) {\n\t\tos_free(mode->channels);\n\t\t(*num_modes)--;\n\t\treturn modes; /* Could not add 802.11b mode */\n\t}\n\n\tfor (i = 0; i < mode11g->num_rates; i++) {\n\t\tif (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&\n\t\t    mode11g->rates[i] != 55 && mode11g->rates[i] != 110)\n\t\t\tcontinue;\n\t\tmode->rates[mode->num_rates] = mode11g->rates[i];\n\t\tmode->num_rates++;\n\t\tif (mode->num_rates == 4)\n\t\t\tbreak;\n\t}\n\n\tif (mode->num_rates == 0) {\n\t\tos_free(mode->channels);\n\t\tos_free(mode->rates);\n\t\t(*num_modes)--;\n\t\treturn modes; /* No 802.11b rates */\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Added 802.11b mode based on 802.11g \"\n\t\t   \"information\");\n\n\treturn modes;\n}\n\n\nstatic void capwap_set_ht40_mode(struct hostapd_hw_modes *mode, int start,\n\t\t\t\t  int end)\n{\n\tint c;\n\n\tfor (c = 0; c < mode->num_channels; c++) {\n\t\tstruct hostapd_channel_data *chan = &mode->channels[c];\n\t\tif (chan->freq - 10 >= start && chan->freq + 10 <= end)\n\t\t\tchan->flag |= HOSTAPD_CHAN_HT40;\n\t}\n}\n\n\nstatic void capwap_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,\n\t\t\t\t      int end)\n{\n\tint c;\n\n\tfor (c = 0; c < mode->num_channels; c++) {\n\t\tstruct hostapd_channel_data *chan = &mode->channels[c];\n\t\tif (!(chan->flag & HOSTAPD_CHAN_HT40))\n\t\t\tcontinue;\n\t\tif (chan->freq - 30 >= start && chan->freq - 10 <= end)\n\t\t\tchan->flag |= HOSTAPD_CHAN_HT40MINUS;\n\t\tif (chan->freq + 10 >= start && chan->freq + 30 <= end)\n\t\t\tchan->flag |= HOSTAPD_CHAN_HT40PLUS;\n\t}\n}\n\n\nstatic void capwap_reg_rule_ht40(struct nlattr *tb[],\n\t\t\t\t  struct phy_info_arg *results)\n{\n\tu32 start, end, max_bw;\n\tu16 m;\n\n\tif (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)\n\t\treturn;\n\n\tstart = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;\n\tend = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;\n\tmax_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;\n\n\twpa_printf(MSG_DEBUG, \"capwap: %u-%u @ %u MHz\",\n\t\t   start, end, max_bw);\n\tif (max_bw < 40)\n\t\treturn;\n\n\tfor (m = 0; m < *results->num_modes; m++) {\n\t\tif (!(results->modes[m].ht_capab &\n\t\t      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))\n\t\t\tcontinue;\n\t\tcapwap_set_ht40_mode(&results->modes[m], start, end);\n\t}\n}\n\n\nstatic void capwap_reg_rule_sec(struct nlattr *tb[],\n\t\t\t\t struct phy_info_arg *results)\n{\n\tu32 start, end, max_bw;\n\tu16 m;\n\n\tif (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||\n\t    tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)\n\t\treturn;\n\n\tstart = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;\n\tend = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;\n\tmax_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;\n\n\tif (max_bw < 20)\n\t\treturn;\n\n\tfor (m = 0; m < *results->num_modes; m++) {\n\t\tif (!(results->modes[m].ht_capab &\n\t\t      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))\n\t\t\tcontinue;\n\t\tcapwap_set_ht40_mode_sec(&results->modes[m], start, end);\n\t}\n}\n\n\nstatic int capwap_get_reg(struct nl_msg *msg, void *arg)\n{\n\tstruct phy_info_arg *results = arg;\n\tstruct nlattr *tb_msg[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct nlattr *nl_rule;\n\tstruct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];\n\tint rem_rule;\n\tstatic struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {\n\t\t[NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },\n\t\t[NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },\n\t};\n\n\tnla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||\n\t    !tb_msg[NL80211_ATTR_REG_RULES]) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No regulatory information \"\n\t\t\t   \"available\");\n\t\treturn NL_SKIP;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Regulatory information - country=%s\",\n\t\t   (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));\n\n\tnla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)\n\t{\n\t\tnla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,\n\t\t\t  nla_data(nl_rule), nla_len(nl_rule), reg_policy);\n\t\tcapwap_reg_rule_ht40(tb_rule, results);\n\t}\n\n\tnla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)\n\t{\n\t\tnla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,\n\t\t\t  nla_data(nl_rule), nla_len(nl_rule), reg_policy);\n\t\tcapwap_reg_rule_sec(tb_rule, results);\n\t}\n\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_set_ht40_flags(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  struct phy_info_arg *results)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_REG);\n\treturn send_and_recv_msgs(drv, msg, capwap_get_reg, results);\n}\n\n\nstatic struct hostapd_hw_modes *\nwpa_driver_capwap_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)\n{\n\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t1.wpa_driver_capwap_get_hw_feature_data \\n\");\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tstruct phy_info_arg result = {\n\t\t.num_modes = num_modes,\n\t\t.modes = NULL,\n\t};\n\n\t*num_modes = 0;\n\t*flags = 0;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn NULL;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tif (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {\n\t\tcapwap_set_ht40_flags(drv, &result);\n\t\treturn wpa_driver_capwap_add_11b(result.modes, num_modes);\n\t}\n\tmsg = NULL;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn NULL;\n}\n\n\n\nint wpa_driver_capwap_send_frame(struct wpa_driver_capwap_data *drv,const void *data, size_t len,int encrypt)\n{\n\t__u8 rtap_hdr[] = {\n\t\t0x00, 0x00, /* radiotap version */\n\t\t0x0e, 0x00, /* radiotap length */\n\t\t0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */\n\t\tIEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */\n\t\t0x00,       /* padding */\n\t\t0x00, 0x00, /* RX and TX flags to indicate that */\n\t\t0x00, 0x00, /* this is the injected frame directly */\n\t};\n\tstruct iovec iov[2] = {\n\t\t{\n\t\t\t.iov_base = &rtap_hdr,\n\t\t\t.iov_len = sizeof(rtap_hdr),\n\t\t},\n\t\t{\n\t\t\t.iov_base = (void *) data,\n\t\t\t.iov_len = len,\n\t\t}\n\t};\n\n\tstruct msghdr msg = {\n\t\t.msg_name = NULL,\n\t\t.msg_namelen = 0,\n\t\t.msg_iov = iov,\n\t\t.msg_iovlen = 2,\n\t\t.msg_control = NULL,\n\t\t.msg_controllen = 0,\n\t\t.msg_flags = 0,\n\t};\n\tint res;\n\n\tif (encrypt)\n\t\trtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;\n\n\tif (drv->monitor_sock < 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No monitor socket available \"\n\t\t\t   \"for %s\", __func__);\n\t\treturn -1;\n\t}\n\n\tres = sendmsg(drv->monitor_sock, &msg, 0);\n\tif (res < 0) {\n\t\twpa_printf(MSG_INFO, \"capwap: sendmsg: %s\", strerror(errno));\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_send_mlme(void *priv, const u8 *data,\n\t\t\t\t\tsize_t data_len)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct ieee80211_mgmt *mgmt;\n\tint encrypt = 1;\n\tu16 fc;\n\n\tmgmt = (struct ieee80211_mgmt *) data;\n\n\n\tfc = le_to_host16(mgmt->frame_control);\n\n\tif (is_sta_interface(drv->nlmode) &&\n\t    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&\n\t    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {\n\t\t/*\n\t\t * The use of last_mgmt_freq is a bit of a hack,\n\t\t * but it works due to the single-threaded nature\n\t\t * of wpa_supplicant.\n\t\t */\n\t\treturn capwap_send_frame_cmd(drv, drv->last_mgmt_freq, 0,\n\t\t\t\t\t      data, data_len, NULL, 1);\n\t}\n\n\tif (drv->no_monitor_iface_capab && is_ap_interface(drv->nlmode)) {\n\t\treturn capwap_send_frame_cmd(drv, drv->ap_oper_freq, 0,\n\t\t\t\t\t      data, data_len,\n\t\t\t\t\t      &drv->send_action_cookie, 0);\n\t}\n\n\tif (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&\n\t    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {\n\t\t/*\n\t\t * Only one of the authentication frame types is encrypted.\n\t\t * In order for static WEP encryption to work properly (i.e.,\n\t\t * to not encrypt the frame), we need to tell mac80211 about\n\t\t * the frames that must not be encrypted.\n\t\t */\n\t\tu16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);\n\t\tu16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);\n\t\tif (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)\n\t\t\tencrypt = 0;\n\t}\n\n\treturn wpa_driver_capwap_send_frame(drv, data, data_len, encrypt);\n}\n\n\nstatic int capwap_set_ap_isolate(struct i802_bss *bss, int enabled)\n{\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\tNLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, enabled);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\treturn -ENOBUFS;\n}\n\n\nstatic int capwap_set_bss(struct i802_bss *bss, int cts, int preamble,\n\t\t\t   int slot, int ht_opmode)\n{\n\twpa_printf(MSG_DEBUG,\"> capwap_set_bss\\n\");\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);\n\n\tif (cts >= 0)\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);\n\tif (preamble >= 0)\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);\n\tif (slot >= 0)\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);\n\tif (ht_opmode >= 0)\n\t\tNLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_set_ap(void *priv,\n\t\t\t\t     struct wpa_driver_ap_params *params)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tu8 cmd = NL80211_CMD_NEW_BEACON;\n\tint ret;\n\tint beacon_set;\n\tint ifindex = if_nametoindex(bss->ifname);\n\tint num_suites;\n\tu32 suites[10];\n\tu32 ver;\n\n\tdrv->mac_mode = params->mac_mode;\n\tbeacon_set = bss->beacon_set;\n\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Set beacon (beacon_set=%d)\",\n\t\t   beacon_set);\n\tif (beacon_set)\n\t\tcmd = NL80211_CMD_SET_BEACON;\n\n\tcapwap_cmd(drv, msg, 0, cmd);\n\tNLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);\n\tNLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);\n\tNLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);\n\tNLA_PUT(msg, NL80211_ATTR_SSID, ac_params.ssid_len,\n\t\tac_params.ssid);\n\tswitch (params->hide_ssid) {\n\tcase NO_SSID_HIDING:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n\t\t\t    NL80211_HIDDEN_SSID_NOT_IN_USE);\n\t\tbreak;\n\tcase HIDDEN_SSID_ZERO_LEN:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n\t\t\t    NL80211_HIDDEN_SSID_ZERO_LEN);\n\t\tbreak;\n\tcase HIDDEN_SSID_ZERO_CONTENTS:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,\n\t\t\t    NL80211_HIDDEN_SSID_ZERO_CONTENTS);\n\t\tbreak;\n\t}\n\tif (params->privacy)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);\n\tif ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==\n\t    (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {\n\t\t/* Leave out the attribute */\n\t} else if (params->auth_algs & WPA_AUTH_ALG_SHARED)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,\n\t\t\t    NL80211_AUTHTYPE_SHARED_KEY);\n\telse\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,\n\t\t\t    NL80211_AUTHTYPE_OPEN_SYSTEM);\n\n\tver = 0;\n\tif (params->wpa_version & WPA_PROTO_WPA)\n\t\tver |= NL80211_WPA_VERSION_1;\n\tif (params->wpa_version & WPA_PROTO_RSN)\n\t\tver |= NL80211_WPA_VERSION_2;\n\tif (ver)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);\n\n\tnum_suites = 0;\n\tif (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)\n\t\tsuites[num_suites++] = WLAN_AKM_SUITE_8021X;\n\tif (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)\n\t\tsuites[num_suites++] = WLAN_AKM_SUITE_PSK;\n\tif (num_suites) {\n\t\tNLA_PUT(msg, NL80211_ATTR_AKM_SUITES,\n\t\t\tnum_suites * sizeof(u32), suites);\n\t}\n\n\tnum_suites = 0;\n\tif (params->pairwise_ciphers & WPA_CIPHER_CCMP)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;\n\tif (params->pairwise_ciphers & WPA_CIPHER_TKIP)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;\n\tif (params->pairwise_ciphers & WPA_CIPHER_WEP104)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;\n\tif (params->pairwise_ciphers & WPA_CIPHER_WEP40)\n\t\tsuites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;\n\tif (num_suites) {\n\t\tNLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,\n\t\t\tnum_suites * sizeof(u32), suites);\n\t}\n\n\tswitch (params->group_cipher) {\n\tcase WPA_CIPHER_CCMP:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_CCMP);\n\t\tbreak;\n\tcase WPA_CIPHER_TKIP:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_TKIP);\n\t\tbreak;\n\tcase WPA_CIPHER_WEP104:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_WEP104);\n\t\tbreak;\n\tcase WPA_CIPHER_WEP40:\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,\n\t\t\t    WLAN_CIPHER_SUITE_WEP40);\n\t\tbreak;\n\t}\n\n\tif (params->beacon_ies) {\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),\n\t\t\twpabuf_head(params->beacon_ies));\n\t}\n\tif (params->proberesp_ies) {\n\t\tNLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,\n\t\t\twpabuf_len(params->proberesp_ies),\n\t\t\twpabuf_head(params->proberesp_ies));\n\t}\n\tif (params->assocresp_ies) {\n\t\tNLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,\n\t\t\twpabuf_len(params->assocresp_ies),\n\t\t\twpabuf_head(params->assocresp_ies));\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Beacon set failed: %d (%s)\",\n\t\t\t   ret, strerror(-ret));\n\t} else {\n\t\tbss->beacon_set = 0;\n\t\tret = capwap_set_ap_isolate(bss, params->isolate);\n\t\tif (!params->isolate && ret) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Ignore AP isolation \"\n\t\t\t\t   \"configuration error since isolation is \"\n\t\t\t\t   \"not used\");\n\t\t\tret = 0;\n\t\t}\n\n\t\tcapwap_set_bss(bss, params->cts_protect, params->preamble,\n\t\t\t\tparams->short_slot_time, params->ht_opmode);\n\t}\n\treturn ret;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_set_freq(struct wpa_driver_capwap_data *drv,\n\t\t\t\t       int freq, int ht_enabled,\n\t\t\t\t       int sec_channel_offset)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t\t1.wpa_driver_capwap_set_freq\\n\");\n\n\tstruct nl_msg *msg;\n\tint ret;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Set freq %d (ht_enabled=%d \"\n\t\t   \"sec_channel_offset=%d)\",\n\t\t   freq, ht_enabled, sec_channel_offset);\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);\n\tif (ht_enabled) {\n\t\tswitch (sec_channel_offset) {\n\t\tcase -1:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,\n\t\t\t\t    NL80211_CHAN_HT40MINUS);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,\n\t\t\t\t    NL80211_CHAN_HT40PLUS);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,\n\t\t\t\t    NL80211_CHAN_HT20);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret == 0)\n\t\treturn 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to set channel (freq=%d): \"\n\t\t   \"%d (%s)\", freq, ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic u32 sta_flags_capwap(int flags)\n{\n\tu32 f = 0;\n\n\tif (flags & WPA_STA_AUTHORIZED)\n\t\tf |= BIT(NL80211_STA_FLAG_AUTHORIZED);\n\tif (flags & WPA_STA_WMM)\n\t\tf |= BIT(NL80211_STA_FLAG_WME);\n\tif (flags & WPA_STA_SHORT_PREAMBLE)\n\t\tf |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);\n\tif (flags & WPA_STA_MFP)\n\t\tf |= BIT(NL80211_STA_FLAG_MFP);\n\tif (flags & WPA_STA_TDLS_PEER)\n\t\tf |= BIT(NL80211_STA_FLAG_TDLS_PEER);\n\n\treturn f;\n}\n\nstatic int wpa_driver_capwap_sta_add(void *priv,\n\t\t\t\t      struct hostapd_sta_add_params *params)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tstruct nl80211_sta_flag_update upd;\n\tint ret = -ENOBUFS;\n\n\n\tif ((params->flags & WPA_STA_TDLS_PEER) &&\n\t    !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n\t\treturn -EOPNOTSUPP;\n\n\tmsg = nlmsg_alloc();\n\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :\n\t\t    NL80211_CMD_NEW_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);\n\n\tNLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,params->supp_rates);\n\n\tif (!params->set) {\n\t\tNLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);\n\t\tNLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,\n\t\t\t    params->listen_interval);\n\t}\n\tif (params->ht_capabilities) {\n\t\tNLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,\n\t\t\tsizeof(*params->ht_capabilities),\n\t\t\tparams->ht_capabilities);\n\t}\n\n\tos_memset(&upd, 0, sizeof(upd));\n\tupd.mask = sta_flags_capwap(params->flags);\n\tupd.set = upd.mask;\n\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\n\tmsg = NULL;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: NL80211_CMD_%s_STATION \"\n\t\t\t   \"result: %d (%s)\", params->set ? \"SET\" : \"NEW\", ret,\n\t\t\t   strerror(-ret));\n\tif (ret == -EEXIST)\n\t\tret = 0;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_sta_remove(void *priv, const u8 *addr)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tif (ret == -ENOENT)\n\t\treturn 0;\n\treturn ret;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic void capwap_remove_iface(struct wpa_driver_capwap_data *drv,\n\t\t\t\t int ifidx)\n{\n\tstruct nl_msg *msg;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Remove interface ifindex=%d\", ifidx);\n\n\t/* stop listening for EAPOL on this interface */\n\tdel_ifidx(drv, ifidx);\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);\n\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n\t\treturn;\n\tmsg = NULL;\n nla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_ERROR, \"Failed to remove interface (ifidx=%d)\", ifidx);\n}\n\n\nstatic const char * nl80211_iftype_str(enum nl80211_iftype mode)\n{\n\tswitch (mode) {\n\tcase NL80211_IFTYPE_ADHOC:\n\t\treturn \"ADHOC\";\n\tcase NL80211_IFTYPE_STATION:\n\t\treturn \"STATION\";\n\tcase NL80211_IFTYPE_AP:\n\t\treturn \"AP\";\n\tcase NL80211_IFTYPE_MONITOR:\n\t\treturn \"MONITOR\";\n\tcase NL80211_IFTYPE_P2P_CLIENT:\n\t\treturn \"P2P_CLIENT\";\n\tcase NL80211_IFTYPE_P2P_GO:\n\t\treturn \"P2P_GO\";\n\tdefault:\n\t\treturn \"unknown\";\n\t}\n}\n\n\nstatic int capwap_create_iface_once(struct wpa_driver_capwap_data *drv,\n\t\t\t\t     const char *ifname,\n\t\t\t\t     enum nl80211_iftype iftype,\n\t\t\t\t     const u8 *addr, int wds)\n{\n\tstruct nl_msg *msg, *flags = NULL;\n\tint ifidx;\n\tint ret = -ENOBUFS;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Create interface iftype %d (%s)\",\n\t\t   iftype, nl80211_iftype_str(iftype));\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);\n\n\tif (iftype == NL80211_IFTYPE_MONITOR) {\n\t\tint err;\n\n\t\tflags = nlmsg_alloc();\n\t\tif (!flags)\n\t\t\tgoto nla_put_failure;\n\n\t\tNLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);\n\n\t\terr = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);\n\n\t\tnlmsg_free(flags);\n\n\t\tif (err)\n\t\t\tgoto nla_put_failure;\n\t} else if (wds) {\n\t\tNLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n nla_put_failure:\n\t\tnlmsg_free(msg);\n\t\twpa_printf(MSG_ERROR, \"Failed to create interface %s: %d (%s)\",\n\t\t\t   ifname, ret, strerror(-ret));\n\t\treturn ret;\n\t}\n\n\tifidx = if_nametoindex(ifname);\n\twpa_printf(MSG_DEBUG, \"capwap: New interface %s created: ifindex=%d\",\n\t\t   ifname, ifidx);\n\n\tif (ifidx <= 0)\n\t\treturn -1;\n\n\t/* start listening for EAPOL on this interface */\n\twpa_printf(MSG_DEBUG, \"start listening for EAPOL on this interface\\n\");\n\tadd_ifidx(drv, ifidx);\n\n\tif (addr && iftype != NL80211_IFTYPE_MONITOR &&\n\t    linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {\n\t\tcapwap_remove_iface(drv, ifidx);\n\t\treturn -1;\n\t}\n\n\treturn ifidx;\n}\n\n\nstatic int capwap_create_iface(struct wpa_driver_capwap_data *drv,\n\t\t\t\tconst char *ifname, enum nl80211_iftype iftype,\n\t\t\t\tconst u8 *addr, int wds)\n{\n\tint ret;\n\n\tret = capwap_create_iface_once(drv, ifname, iftype, addr, wds);\n\n\t/* if error occurred and interface exists already */\n\tif (ret == -ENFILE && if_nametoindex(ifname)) {\n\t\twpa_printf(MSG_INFO, \"Try to remove and re-create %s\", ifname);\n\n\t\t/* Try to remove the interface that was already there. */\n\t\tcapwap_remove_iface(drv, if_nametoindex(ifname));\n\n\t\t/* Try to create the interface again */\n\t\tret = capwap_create_iface_once(drv, ifname, iftype, addr,\n\t\t\t\t\t\twds);\n\t}\n\n\tif (ret >= 0 && is_p2p_interface(iftype))\n\t\tcapwap_disable_11b_rates(drv, ret, 1);\n\n\treturn ret;\n}\n\n\nstatic void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)\n{\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\tunion wpa_event_data event;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\tos_memset(&event, 0, sizeof(event));\n\tevent.tx_status.type = WLAN_FC_GET_TYPE(fc);\n\tevent.tx_status.stype = WLAN_FC_GET_STYPE(fc);\n\tevent.tx_status.dst = hdr->addr1;\n\tevent.tx_status.data = buf;\n\tevent.tx_status.data_len = len;\n\tevent.tx_status.ack = ok;\n\twpa_supplicant_event(ctx, EVENT_TX_STATUS, &event);\n\n}\n\n\nstatic void from_unknown_sta(struct wpa_driver_capwap_data *drv,\n\t\t\t     u8 *buf, size_t len)\n{\n\tstruct ieee80211_hdr *hdr = (void *)buf;\n\tu16 fc;\n\tunion wpa_event_data event;\n\n\tif (len < sizeof(*hdr))\n\t\treturn;\n\n\tfc = le_to_host16(hdr->frame_control);\n\n\tos_memset(&event, 0, sizeof(event));\n\tevent.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);\n\tevent.rx_from_unknown.addr = hdr->addr2;\n\tevent.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==\n\t\t(WLAN_FC_FROMDS | WLAN_FC_TODS);\n\twpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);\n}\n\n\nstatic void handle_frame(struct wpa_driver_capwap_data *drv,\n\t\t\t u8 *buf, size_t len, int datarate, int ssi_signal)\n{\n\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\tunion wpa_event_data event;\n\n\thdr = (struct ieee80211_hdr *) buf;\n\tfc = le_to_host16(hdr->frame_control);\n\n\tswitch (WLAN_FC_GET_TYPE(fc)) {\n\tcase WLAN_FC_TYPE_MGMT:\n\t\tos_memset(&event, 0, sizeof(event));\n\t\tevent.rx_mgmt.frame = buf;\n\t\tevent.rx_mgmt.frame_len = len;\n\t\tevent.rx_mgmt.datarate = datarate;\n\t\tevent.rx_mgmt.ssi_signal = ssi_signal;\n\t\twpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);\n\t\tbreak;\n\tcase WLAN_FC_TYPE_CTRL:\n\t\t/* can only get here with PS-Poll frames */\n\t\twpa_printf(MSG_DEBUG, \"CTRL\");\n\t\tfrom_unknown_sta(drv, buf, len);\n\t\tbreak;\n\tcase WLAN_FC_TYPE_DATA:\n\t\tfrom_unknown_sta(drv, buf, len);\n\n\t\tbreak;\n\t}\n}\n\n\nstatic void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx){\n\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\tint len;\n        int close = 0;\n\tunsigned char buf[3000];\n\tstruct ieee80211_radiotap_iterator iter;\n\tint ret;\n\tint datarate = 0, ssi_signal = 0;\n\tint injected = 0, failed = 0, rxflags = 0;\n\tlen = recv(sock, buf, sizeof(buf), 0);\n\n\t/* Scarto i pacchetti Beacon ricevutti */\n\tif(buf[14]==0x80 )return;// Beacon Frame\n\n\tif (len < 0) {\n\t\tperror(\"recv\");\n\t\treturn;\n\t}\n\n\n\tif (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {\n\t\twpa_printf(MSG_DEBUG, \"received invalid radiotap frame\\n\");\n\t\treturn;\n\t}\n\n\twhile (1) {\n\t\tret = ieee80211_radiotap_iterator_next(&iter);\n\t\tif (ret == -ENOENT)\n\t\t\tbreak;\n\t\tif (ret) {\n\t\t\twpa_printf(MSG_DEBUG, \"received invalid radiotap frame (%d)\\n\", ret);\n\t\t\treturn;\n\t\t}\n\t\tswitch (iter.this_arg_index) {\n\t\tcase IEEE80211_RADIOTAP_FLAGS:\n\t\t\tif (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)\n\t\t\t\tlen -= 4;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_RX_FLAGS:\n\t\t\trxflags = 1;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_TX_FLAGS:\n\t\t\tinjected = 1;\n\t\t\tfailed = le_to_host16((*(uint16_t *) iter.this_arg)) &\n\t\t\t\t\tIEEE80211_RADIOTAP_F_TX_FAIL;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_DATA_RETRIES:\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_CHANNEL:\n\t\t\t/* TODO: convert from freq/flags to channel number */\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_RATE:\n\t\t\tdatarate = *iter.this_arg * 5;\n\t\t\tbreak;\n\t\tcase IEEE80211_RADIOTAP_DB_ANTSIGNAL:\n\t\t\tssi_signal = *iter.this_arg;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (rxflags && injected)\n\t\treturn;\n\n\tstruct ieee80211_hdr *hdr;\n\tu16 fc;\n\n\thdr = (struct ieee80211_hdr *)(buf + iter.max_length);\n\tfc = le_to_host16(hdr->frame_control);\n\n\tswitch (WLAN_FC_GET_TYPE(fc)) {\n\tcase WLAN_FC_TYPE_DATA:\n\t\twpa_printf(MSG_DEBUG, \"EAPOL Data Frame 3 (%d)\\n\", len - iter.max_length);\n\t\tipc_send_80211_to_ac(generic_wtp_info.fd_ipc, buf  + iter.max_length,len - iter.max_length);\n\t\treturn;\n\n\tcase WLAN_FC_TYPE_MGMT:\n\t\tswitch (WLAN_FC_GET_STYPE(fc)) {\n\t\tcase WLAN_FC_STYPE_BEACON:\n\t\t\t/* TODO: why are beacon frames not forwarded to hostapd */\n\t\t\treturn;\n\n\t\tcase WLAN_FC_STYPE_PROBE_REQ:\n\t\tcase WLAN_FC_STYPE_PROBE_RESP:\n\t\t\t/* handled by hostapd */\n\t\t\tbreak;\n\n\t\tcase WLAN_FC_STYPE_ASSOC_REQ:\n\t\tcase WLAN_FC_STYPE_REASSOC_REQ:\n\t\t\t/* always forward to AC */\n\t\t\tipc_send_80211_to_ac(generic_wtp_info.fd_ipc,buf  + iter.max_length,len - iter.max_length);\n\n\t\t\tif (drv->mac_mode == CW_SPLIT_MAC)\n\t\t\t\t/* in Split MAC mode the AC handles the rest */\n\t\t\t\treturn;\n\n\t\t\tbreak;\n\n\t\tcase WLAN_FC_STYPE_ASSOC_RESP:\n\t\tcase WLAN_FC_STYPE_REASSOC_RESP:\n\t\t\tif (drv->mac_mode == CW_SPLIT_MAC)\n\t\t\t\t/* don't mirror responses back to the AC */\n\t\t\t\treturn;\n\n\t\t\t/* handled by hostapd in Local MAC Mode*/\n\t\t\tbreak;\n\n\t\tcase WLAN_FC_STYPE_AUTH:\n\t\t\tif (!injected)\n\t\t\t\t/* forward to AC */\n\t\t\t\tipc_send_80211_to_ac(generic_wtp_info.fd_ipc,buf  + iter.max_length,len - iter.max_length);\n\n\t\t\tif (drv->mac_mode == CW_SPLIT_MAC)\n\t\t\t\t/* handled by hostapd in Local MAC Mode*/\n\t\t\t\treturn;\n\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t// All other packet sent to AC\n\t\t\tipc_send_80211_to_ac(generic_wtp_info.fd_ipc,buf  + iter.max_length,len - iter.max_length);\n\t\t\treturn;\n\t\t}\n\t\tbreak;\n\n\tdefault:\n\t\twpa_printf(MSG_ERROR, \"ERROR RECV CONTROLL TRAFIC on MONITOR INTERFACE\");\n\t\treturn;\n\t}\n\n\tif (!injected)\n\t\thandle_frame(drv, buf + iter.max_length,\n\t\t\t     len - iter.max_length, datarate, ssi_signal);\n\telse\n\t\thandle_tx_callback(drv->ctx, buf + iter.max_length,\n\t\t\t\t   len - iter.max_length, !failed);\n\n\tif (drv->mac_mode == CW_SPLIT_MAC &&\n\t    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&\n\t    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ)\n\t\tipc_send_80211_to_ac(generic_wtp_info.fd_ipc, buf  + iter.max_length,len - iter.max_length);\n}\n\n\n/*\n * we post-process the filter code later and rewrite\n * this to the offset to the last instruction\n */\n#define PASS\t0xFF\n#define FAIL\t0xFE\n\nstatic struct sock_filter msock_filter_insns[] = {\n\t/*\n\t * do a little-endian load of the radiotap length field\n\t */\n\t/* load lower byte into A */\n\tBPF_STMT(BPF_LD  | BPF_B | BPF_ABS, 2),\n\t/* put it into X (== index register) */\n\tBPF_STMT(BPF_MISC| BPF_TAX, 0),\n\t/* load upper byte into A */\n\tBPF_STMT(BPF_LD  | BPF_B | BPF_ABS, 3),\n\t/* left-shift it by 8 */\n\tBPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8),\n\t/* or with X */\n\tBPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0),\n\t/* put result into X */\n\tBPF_STMT(BPF_MISC| BPF_TAX, 0),\n\n\t/*\n\t * Allow management frames through, this also gives us those\n\t * management frames that we sent ourselves with status\n\t */\n\t/* load the lower byte of the IEEE 802.11 frame control field */\n\tBPF_STMT(BPF_LD  | BPF_B | BPF_IND, 0),\n\t/* mask off frame type and version */\n\tBPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF),\n\t/* accept frame if it's both 0, fall through otherwise */\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0),\n\n\t/*\n\t * TODO: add a bit to radiotap RX flags that indicates\n\t * that the sending station is not associated, then\n\t * add a filter here that filters on our DA and that flag\n\t * to allow us to deauth frames to that bad station.\n\t *\n\t * For now allow all To DS data frames through.\n\t */\n\t/* load the IEEE 802.11 frame control field */\n\tBPF_STMT(BPF_LD  | BPF_H | BPF_IND, 0),\n\t/* mask off frame type, version and DS status */\n\tBPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03),\n\t/* accept frame if version 0, type 2 and To DS, fall through otherwise\n\t */\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0),\n\n#if 0\n\t/*\n\t * drop non-data frames\n\t */\n\t/* load the lower byte of the frame control field */\n\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 0),\n\t/* mask off QoS bit */\n\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x0c),\n\t/* drop non-data frames */\n\tBPF_JUMP(BPF_JMP  | BPF_JEQ | BPF_K, 8, 0, FAIL),\n#endif\n\t/* load the upper byte of the frame control field */\n\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 1),\n\t/* mask off toDS/fromDS */\n\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x03),\n\t/* accept WDS frames */\n\tBPF_JUMP(BPF_JMP  | BPF_JEQ | BPF_K, 3, PASS, 0),\n\n\t/*\n\t * add header length to index\n\t */\n\t/* load the lower byte of the frame control field */\n\tBPF_STMT(BPF_LD   | BPF_B | BPF_IND, 0),\n\t/* mask off QoS bit */\n\tBPF_STMT(BPF_ALU  | BPF_AND | BPF_K, 0x80),\n\t/* right shift it by 6 to give 0 or 2 */\n\tBPF_STMT(BPF_ALU  | BPF_RSH | BPF_K, 6),\n\t/* add data frame header length */\n\tBPF_STMT(BPF_ALU  | BPF_ADD | BPF_K, 24),\n\t/* add index, was start of 802.11 header */\n\tBPF_STMT(BPF_ALU  | BPF_ADD | BPF_X, 0),\n\t/* move to index, now start of LL header */\n\tBPF_STMT(BPF_MISC | BPF_TAX, 0),\n\n\t/*\n\t * Accept empty data frames, we use those for\n\t * polling activity.\n\t */\n\tBPF_STMT(BPF_LD  | BPF_W | BPF_LEN, 0),\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0),\n\n\t/*\n\t * Accept EAPOL frames\n\t */\n\tBPF_STMT(BPF_LD  | BPF_W | BPF_IND, 0),\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL),\n\tBPF_STMT(BPF_LD  | BPF_W | BPF_IND, 4),\n\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL),\n\n\t/* keep these last two statements or change the code below */\n\t/* return 0 == \"DROP\" */\n\tBPF_STMT(BPF_RET | BPF_K, 0),\n\t/* return ~0 == \"keep all\" */\n\tBPF_STMT(BPF_RET | BPF_K, ~0),\n};\n\nstatic struct sock_fprog msock_filter = {\n\t.len = sizeof(msock_filter_insns)/sizeof(msock_filter_insns[0]),\n\t.filter = msock_filter_insns,\n};\n\n\nstatic int add_monitor_filter(int s)\n{\n\tint idx;\n\n\t/* rewrite all PASS/FAIL jump offsets */\n\tfor (idx = 0; idx < msock_filter.len; idx++) {\n\t\tstruct sock_filter *insn = &msock_filter_insns[idx];\n\n\t\tif (BPF_CLASS(insn->code) == BPF_JMP) {\n\t\t\tif (insn->code == (BPF_JMP|BPF_JA)) {\n\t\t\t\tif (insn->k == PASS)\n\t\t\t\t\tinsn->k = msock_filter.len - idx - 2;\n\t\t\t\telse if (insn->k == FAIL)\n\t\t\t\t\tinsn->k = msock_filter.len - idx - 3;\n\t\t\t}\n\n\t\t\tif (insn->jt == PASS)\n\t\t\t\tinsn->jt = msock_filter.len - idx - 2;\n\t\t\telse if (insn->jt == FAIL)\n\t\t\t\tinsn->jt = msock_filter.len - idx - 3;\n\n\t\t\tif (insn->jf == PASS)\n\t\t\t\tinsn->jf = msock_filter.len - idx - 2;\n\t\t\telse if (insn->jf == FAIL)\n\t\t\t\tinsn->jf = msock_filter.len - idx - 3;\n\t\t}\n\t}\n\n\tif (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER,\n\t\t       &msock_filter, sizeof(msock_filter))) {\n\t\tperror(\"SO_ATTACH_FILTER\");\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\n\nstatic void capwap_remove_monitor_interface(\n\tstruct wpa_driver_capwap_data *drv)\n{\n\n\tif (drv->monitor_ifidx >= 0) {\n\t\tcapwap_remove_iface(drv, drv->monitor_ifidx);\n\t\tdrv->monitor_ifidx = -1;\n\t}\n\tif (drv->monitor_sock >= 0) {\n\t\teloop_unregister_read_sock(drv->monitor_sock);\n\t\tclose(drv->monitor_sock);\n\t\tdrv->monitor_sock = -1;\n\t}\n}\n\n\nstatic int capwap_create_monitor_interface(struct wpa_driver_capwap_data *drv){\n\twpa_printf(MSG_DEBUG, \"8.5   capwap_create_monitor_interface\\n\");\n\tchar buf[IFNAMSIZ];\n\tstruct sockaddr_ll ll;\n\tint optval;\n\tsocklen_t optlen;\n\n\tif (os_strncmp(drv->first_bss.ifname, \"p2p-\", 4) == 0) {\n\t\t/*\n\t\t * P2P interface name is of the format p2p-%s-%d. For monitor\n\t\t * interface name corresponding to P2P GO, replace \"p2p-\" with\n\t\t * \"mon-\" to retain the same interface name length and to\n\t\t * indicate that it is a monitor interface.\n\t\t */\n\t\tsnprintf(buf, IFNAMSIZ, \"mon-%s\", drv->first_bss.ifname + 4);\n\t} else {\n\t\t/* Non-P2P interface with AP functionality. */\n\t\tsnprintf(buf, IFNAMSIZ, \"mon.%s\", drv->first_bss.ifname);\n\t}\n\n\tbuf[IFNAMSIZ - 1] = '\\0';\n\n\tdrv->monitor_ifidx =\n\t\tcapwap_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,\n\t\t\t\t     0);\n\n\tif (drv->monitor_ifidx == -EOPNOTSUPP) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Driver does not support \"\n\t\t\t   \"monitor interface type - try to run without it\");\n\t\tdrv->no_monitor_iface_capab = 1;\n\t}\n\n\tif (drv->monitor_ifidx < 0)\n\t\treturn -1;\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))\n\t\tgoto error;\n\n\tmemset(&ll, 0, sizeof(ll));\n\tll.sll_family = AF_PACKET;\n\tll.sll_ifindex = drv->monitor_ifidx;\n\tdrv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n\tif (drv->monitor_sock < 0) {\n\t\tperror(\"socket[PF_PACKET,SOCK_RAW]\");\n\t\tgoto error;\n\t}\n\n\tif (add_monitor_filter(drv->monitor_sock)) {\n\t\twpa_printf(MSG_INFO, \"Failed to set socket filter for monitor \"\n\t\t\t   \"interface; do filtering in user space\");\n\t\t/* This works, but will cost in performance. */\n\t}\n\n\tif (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {\n\t\tperror(\"monitor socket bind\");\n\t\tgoto error;\n\t}\n\n\toptlen = sizeof(optval);\n\toptval = 20;\n\tif (setsockopt\n\t    (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {\n\t\tperror(\"Failed to set socket priority\");\n\t\tgoto error;\n\t}\n\n\tif (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,\n\t\t\t\t\tdrv, NULL)) {\n\t\twpa_printf(MSG_DEBUG, \"Could not register monitor read socket\\n\");\n\t\tgoto error;\n\t}\n\n\n\treturn 0;\n error:\n\tcapwap_remove_monitor_interface(drv);\n\treturn -1;\n}\n\n\n#ifdef CONFIG_AP\nstatic int capwap_send_eapol_data(struct i802_bss *bss,\n\t\t\t\t   const u8 *addr, const u8 *data,\n\t\t\t\t   size_t data_len, const u8 *own_addr)\n{\n\twpa_printf(MSG_DEBUG, \"capwap_send_eapol_data\\n\");\n\tif (bss->drv->l2 == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No l2_packet to send EAPOL\");\n\t\treturn -1;\n\t}\n\n\tif (l2_packet_send(bss->drv->l2, addr, ETH_P_EAPOL, data, data_len) <\n\t    0)\n\t\treturn -1;\n\treturn 0;\n}\n#endif /* CONFIG_AP */\n\n\nstatic const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };\n\nstatic int wpa_driver_capwap_hapd_send_eapol(\n\tvoid *priv, const u8 *addr, const u8 *data,\n\tsize_t data_len, int encrypt, const u8 *own_addr, u32 flags)\n{\n\twpa_printf(MSG_DEBUG, \"-------------- wpa_driver_capwap_hapd_send_eapol\\n\");\n\treturn 0;\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct ieee80211_hdr *hdr;\n\tsize_t len;\n\tu8 *pos;\n\tint res;\n\tint qos = flags & WPA_STA_WMM;\n\n#ifdef CONFIG_AP\n\tif (drv->no_monitor_iface_capab)\n\t\treturn capwap_send_eapol_data(bss, addr, data, data_len,\n\t\t\t\t\t       own_addr);\n#endif /* CONFIG_AP */\n\n\tlen = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +\n\t\tdata_len;\n\thdr = os_zalloc(len);\n\tif (hdr == NULL) {\n\t\twpa_printf(MSG_DEBUG, \"malloc() failed for i802_send_data(len=%lu)\\n\",\n\t\t       (unsigned long) len);\n\t\treturn -1;\n\t}\n\n\thdr->frame_control =\n\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);\n\thdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);\n\tif (encrypt)\n\t\thdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);\n\tif (qos) {\n\t\thdr->frame_control |=\n\t\t\thost_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);\n\t}\n\n\tmemcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);\n\tmemcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);\n\tmemcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);\n\tpos = (u8 *) (hdr + 1);\n\n\tif (qos) {\n\t\t/* add an empty QoS header if needed */\n\t\tpos[0] = 0;\n\t\tpos[1] = 0;\n\t\tpos += 2;\n\t}\n\n\tmemcpy(pos, rfc1042_header, sizeof(rfc1042_header));\n\tpos += sizeof(rfc1042_header);\n\tWPA_PUT_BE16(pos, ETH_P_PAE);\n\tpos += 2;\n\tmemcpy(pos, data, data_len);\n\n\tres = wpa_driver_capwap_send_frame(drv, (u8 *) hdr, len, encrypt);\n\tif (res < 0) {\n\t\twpa_printf(MSG_ERROR, \"i802_send_eapol - packet len: %lu - \"\n\t\t\t   \"failed: %d (%s)\",\n\t\t\t   (unsigned long) len, errno, strerror(errno));\n\t}\n\tos_free(hdr);\n\n\treturn res;\n}\n\n\nstatic int wpa_driver_capwap_sta_set_flags(void *priv, const u8 *addr,\n\t\t\t\t\t    int total_flags,\n\t\t\t\t\t    int flags_or, int flags_and)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg, *flags = NULL;\n\tstruct nl80211_sta_flag_update upd;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tflags = nlmsg_alloc();\n\tif (!flags) {\n\t\tnlmsg_free(msg);\n\t\treturn -ENOMEM;\n\t}\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\n\t/*\n\t * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This\n\t * can be removed eventually.\n\t */\n\tif (total_flags & WPA_STA_AUTHORIZED)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);\n\n\tif (total_flags & WPA_STA_WMM)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);\n\n\tif (total_flags & WPA_STA_SHORT_PREAMBLE)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);\n\n\tif (total_flags & WPA_STA_MFP)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);\n\n\tif (total_flags & WPA_STA_TDLS_PEER)\n\t\tNLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);\n\n\tif (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))\n\t\tgoto nla_put_failure;\n\n\tos_memset(&upd, 0, sizeof(upd));\n\tupd.mask = sta_flags_capwap(flags_or | ~flags_and);\n\tupd.set = sta_flags_capwap(flags_or);\n\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n\n\tnlmsg_free(flags);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\tnlmsg_free(flags);\n\treturn -ENOBUFS;\n}\n\n\nstatic int wpa_driver_capwap_ap(struct wpa_driver_capwap_data *drv,\n\t\t\t\t struct wpa_driver_associate_params *params)\n{\n\tenum nl80211_iftype nlmode;\n\n\tif (params->p2p) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Setup AP operations for P2P \"\n\t\t\t   \"group (GO)\");\n\t\tnlmode = NL80211_IFTYPE_P2P_GO;\n\t} else\n\t\tnlmode = NL80211_IFTYPE_AP;\n\n\tif (wpa_driver_capwap_set_mode(&drv->first_bss, nlmode) ||\n\t    wpa_driver_capwap_set_freq(drv, params->freq, 0, 0)) {\n\t\tcapwap_remove_monitor_interface(drv);\n\t\treturn -1;\n\t}\n\n\tif (drv->no_monitor_iface_capab) {\n\t\tif (wpa_driver_capwap_probe_req_report(&drv->first_bss, 1) < 0)\n\t\t{\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to enable \"\n\t\t\t\t   \"Probe Request frame reporting in AP mode\");\n\t\t\t/* Try to survive without this */\n\t\t}\n\t}\n\n\tdrv->ap_oper_freq = params->freq;\n\n\treturn 0;\n}\n\n\nstatic int capwap_leave_ibss(struct wpa_driver_capwap_data *drv)\n{\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Leave IBSS failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tgoto nla_put_failure;\n\t}\n\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Leave IBSS request sent successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_ibss(struct wpa_driver_capwap_data *drv,\n\t\t\t\t   struct wpa_driver_associate_params *params)\n{\n\tstruct nl_msg *msg;\n\tint ret = -1;\n\tint count = 0;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS (ifindex=%d)\", drv->ifindex);\n\n\tif (wpa_driver_capwap_set_mode(&drv->first_bss,\n\t\t\t\t\tNL80211_IFTYPE_ADHOC)) {\n\t\twpa_printf(MSG_INFO, \"capwap: Failed to set interface into \"\n\t\t\t   \"IBSS mode\");\n\t\treturn -1;\n\t}\n\nretry:\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\tif (ac_params.ssid == NULL || ac_params.ssid_len > sizeof(drv->ssid))\n\t\tgoto nla_put_failure;\n\n\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t  ac_params.ssid, ac_params.ssid_len);\n\tNLA_PUT(msg, NL80211_ATTR_SSID, ac_params.ssid_len,\n\t\tac_params.ssid);\n\tos_memcpy(drv->ssid, ac_params.ssid, ac_params.ssid_len);\n\tdrv->ssid_len = ac_params.ssid_len;\n\n\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\n\tret = capwap_set_conn_keys(params, msg);\n\tif (ret)\n\t\tgoto nla_put_failure;\n\n\tif (params->wpa_ie) {\n\t\twpa_hexdump(MSG_DEBUG,\n\t\t\t    \"  * Extra IEs for Beacon/Probe Response frames\",\n\t\t\t    params->wpa_ie, params->wpa_ie_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n\t\t\tparams->wpa_ie);\n\t}\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS failed: ret=%d (%s)\",\n\t\t\t   ret, strerror(-ret));\n\t\tcount++;\n\t\tif (ret == -EALREADY && count == 1) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Retry IBSS join after \"\n\t\t\t\t   \"forced leave\");\n\t\t\tcapwap_leave_ibss(drv);\n\t\t\tnlmsg_free(msg);\n\t\t\tgoto retry;\n\t\t}\n\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Join IBSS request sent successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic unsigned int capwap_get_assoc_bssid(struct wpa_driver_capwap_data *drv,\n\t\t\t\t\t    u8 *bssid)\n{\n\tstruct nl_msg *msg;\n\tint ret;\n\tstruct capwap_bss_info_arg arg;\n\n\tos_memset(&arg, 0, sizeof(arg));\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\tgoto nla_put_failure;\n\n\tcapwap_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\n\targ.drv = drv;\n\tret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\tif (is_zero_ether_addr(arg.assoc_bssid))\n\t\t\treturn -ENOTCONN;\n\t\tos_memcpy(bssid, arg.assoc_bssid, ETH_ALEN);\n\t\treturn 0;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Scan result fetch failed: ret=%d \"\n\t\t   \"(%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn drv->assoc_freq;\n}\n\n\nstatic int capwap_disconnect(struct wpa_driver_capwap_data *drv,\n\t\t\t      const u8 *bssid)\n{\n\tu8 addr[ETH_ALEN];\n\n\tif (bssid == NULL) {\n\t\tint res = capwap_get_assoc_bssid(drv, addr);\n\t\tif (res)\n\t\t\treturn res;\n\t\tbssid = addr;\n\t}\n\n\treturn wpa_driver_capwap_disconnect(drv, bssid,\n\t\t\t\t\t     WLAN_REASON_PREV_AUTH_NOT_VALID);\n}\n\n\nstatic int wpa_driver_capwap_connect(\n\tstruct wpa_driver_capwap_data *drv,\n\tstruct wpa_driver_associate_params *params)\n{\n\tstruct nl_msg *msg;\n\tenum nl80211_auth_type type;\n\tint ret = 0;\n\tint algs;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Connect (ifindex=%d)\", drv->ifindex);\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_CONNECT);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tif (params->bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n\t}\n\tif (params->freq) {\n\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\t}\n\tif (ac_params.ssid) {\n\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t\t  ac_params.ssid, ac_params.ssid_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_SSID, ac_params.ssid_len,\n\t\t\tac_params.ssid);\n\t\tif (ac_params.ssid_len > sizeof(drv->ssid))\n\t\t\tgoto nla_put_failure;\n\t\tos_memcpy(drv->ssid, ac_params.ssid, ac_params.ssid_len);\n\t\tdrv->ssid_len = ac_params.ssid_len;\n\t}\n\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->wpa_ie, params->wpa_ie_len);\n\tif (params->wpa_ie)\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n\t\t\tparams->wpa_ie);\n\n\talgs = 0;\n\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n\t\talgs++;\n\tif (params->auth_alg & WPA_AUTH_ALG_SHARED)\n\t\talgs++;\n\tif (params->auth_alg & WPA_AUTH_ALG_LEAP)\n\t\talgs++;\n\tif (algs > 1) {\n\t\twpa_printf(MSG_DEBUG, \"  * Leave out Auth Type for automatic \"\n\t\t\t   \"selection\");\n\t\tgoto skip_auth_type;\n\t}\n\n\tif (params->auth_alg & WPA_AUTH_ALG_OPEN)\n\t\ttype = NL80211_AUTHTYPE_OPEN_SYSTEM;\n\telse if (params->auth_alg & WPA_AUTH_ALG_SHARED)\n\t\ttype = NL80211_AUTHTYPE_SHARED_KEY;\n\telse if (params->auth_alg & WPA_AUTH_ALG_LEAP)\n\t\ttype = NL80211_AUTHTYPE_NETWORK_EAP;\n\telse if (params->auth_alg & WPA_AUTH_ALG_FT)\n\t\ttype = NL80211_AUTHTYPE_FT;\n\telse\n\t\tgoto nla_put_failure;\n\n\twpa_printf(MSG_DEBUG, \"  * Auth Type %d\", type);\n\tNLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);\n\nskip_auth_type:\n\tif (params->wpa_proto) {\n\t\tenum nl80211_wpa_versions ver = 0;\n\n\t\tif (params->wpa_proto & WPA_PROTO_WPA)\n\t\t\tver |= NL80211_WPA_VERSION_1;\n\t\tif (params->wpa_proto & WPA_PROTO_RSN)\n\t\t\tver |= NL80211_WPA_VERSION_2;\n\n\t\twpa_printf(MSG_DEBUG, \"  * WPA Versions 0x%x\", ver);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);\n\t}\n\n\tif (params->pairwise_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->pairwise_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);\n\t}\n\n\tif (params->group_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->group_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);\n\t}\n\n\tif (params->key_mgmt_suite == KEY_MGMT_802_1X ||\n\t    params->key_mgmt_suite == KEY_MGMT_PSK) {\n\t\tint mgmt = WLAN_AKM_SUITE_PSK;\n\n\t\tswitch (params->key_mgmt_suite) {\n\t\tcase KEY_MGMT_802_1X:\n\t\t\tmgmt = WLAN_AKM_SUITE_8021X;\n\t\t\tbreak;\n\t\tcase KEY_MGMT_PSK:\n\t\tdefault:\n\t\t\tmgmt = WLAN_AKM_SUITE_PSK;\n\t\t\tbreak;\n\t\t}\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);\n\t}\n\n\tret = capwap_set_conn_keys(params, msg);\n\tif (ret)\n\t\tgoto nla_put_failure;\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME connect failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\t/*\n\t\t * cfg80211 does not currently accept new connection if we are\n\t\t * already connected. As a workaround, force disconnection and\n\t\t * try again once the driver indicates it completed\n\t\t * disconnection.\n\t\t */\n\t\tif (ret == -EALREADY)\n\t\t\tcapwap_disconnect(drv, params->bssid);\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Connect request send successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n\n}\n\n\nstatic int wpa_driver_capwap_associate(\n\tvoid *priv, struct wpa_driver_associate_params *params)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1;\n\tstruct nl_msg *msg;\n\n\tif (params->mode == IEEE80211_MODE_AP)\n\t\treturn wpa_driver_capwap_ap(drv, params);\n\n\tif (params->mode == IEEE80211_MODE_IBSS)\n\t\treturn wpa_driver_capwap_ibss(drv, params);\n\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {\n\t\tenum nl80211_iftype nlmode = params->p2p ?\n\t\t\tNL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;\n\n\t\tif (wpa_driver_capwap_set_mode(priv, nlmode) < 0)\n\t\t\treturn -1;\n\t\treturn wpa_driver_capwap_connect(drv, params);\n\t}\n\n\tdrv->associated = 0;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Associate (ifindex=%d)\",\n\t\t   drv->ifindex);\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tif (params->bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);\n\t}\n\tif (params->freq) {\n\t\twpa_printf(MSG_DEBUG, \"  * freq=%d\", params->freq);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);\n\t\tdrv->assoc_freq = params->freq;\n\t} else\n\t\tdrv->assoc_freq = 0;\n\tif (ac_params.ssid) {\n\t\twpa_hexdump_ascii(MSG_DEBUG, \"  * SSID\",\n\t\t\t\t  ac_params.ssid, ac_params.ssid_len);\n\t\tNLA_PUT(msg, NL80211_ATTR_SSID, ac_params.ssid_len,\n\t\t\tac_params.ssid);\n\t\tif (ac_params.ssid_len > sizeof(drv->ssid))\n\t\t\tgoto nla_put_failure;\n\t\tos_memcpy(drv->ssid, ac_params.ssid, ac_params.ssid_len);\n\t\tdrv->ssid_len = ac_params.ssid_len;\n\t}\n\twpa_hexdump(MSG_DEBUG, \"  * IEs\", params->wpa_ie, params->wpa_ie_len);\n\tif (params->wpa_ie)\n\t\tNLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,\n\t\t\tparams->wpa_ie);\n\n\tif (params->pairwise_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->pairwise_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\twpa_printf(MSG_DEBUG, \"  * pairwise=0x%x\", cipher);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);\n\t}\n\n\tif (params->group_suite != CIPHER_NONE) {\n\t\tint cipher;\n\n\t\tswitch (params->group_suite) {\n\t\tcase CIPHER_WEP40:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP40;\n\t\t\tbreak;\n\t\tcase CIPHER_WEP104:\n\t\t\tcipher = WLAN_CIPHER_SUITE_WEP104;\n\t\t\tbreak;\n\t\tcase CIPHER_CCMP:\n\t\t\tcipher = WLAN_CIPHER_SUITE_CCMP;\n\t\t\tbreak;\n\t\tcase CIPHER_TKIP:\n\t\tdefault:\n\t\t\tcipher = WLAN_CIPHER_SUITE_TKIP;\n\t\t\tbreak;\n\t\t}\n\t\twpa_printf(MSG_DEBUG, \"  * group=0x%x\", cipher);\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);\n\t}\n\n#ifdef CONFIG_IEEE80211W\n\tif (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);\n#endif /* CONFIG_IEEE80211W */\n\n\tNLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);\n\n\tif (params->prev_bssid) {\n\t\twpa_printf(MSG_DEBUG, \"  * prev_bssid=\" MACSTR,\n\t\t\t   MAC2STR(params->prev_bssid));\n\t\tNLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,\n\t\t\tparams->prev_bssid);\n\t}\n\n\tif (params->p2p)\n\t\twpa_printf(MSG_DEBUG, \"  * P2P group\");\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: MLME command failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t\tcapwap_dump_scan(drv);\n\t\tgoto nla_put_failure;\n\t}\n\tret = 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Association request send \"\n\t\t   \"successfully\");\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int capwap_set_mode(struct wpa_driver_capwap_data *drv,\n\t\t\t    int ifindex, enum nl80211_iftype mode)\n{\n\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t1.wpa_driver_capwap_set_mode\\n\");\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Set mode ifindex %d iftype %d (%s)\",\n\t\t   ifindex, mode, nl80211_iftype_str(mode));\n\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\n\tmsg = NULL;\n\n\tif (!ret)\n\t\treturn 0;\n\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to set interface %d to mode %d:\"\n\t\t   \" %d (%s)\", ifindex, mode, ret, strerror(-ret));\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_set_mode(struct i802_bss *bss,\n\t\t\t\t       enum nl80211_iftype nlmode)\n{\n\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t6.wpa_driver_capwap_set_mode\\n\");\n\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1;\n\tint i;\n\tint was_ap = is_ap_interface(drv->nlmode);\n\n\tif (capwap_set_mode(drv, drv->ifindex, nlmode) == 0) {\n\t\tdrv->nlmode = nlmode;\n\t\tret = 0;\n\t\tgoto done;\n\t}\n\n\tif (nlmode == drv->nlmode) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface already in \"\n\t\t\t   \"requested mode - ignore error\");\n\t\tret = 0;\n\t\tgoto done; /* Already in the requested mode */\n\t}\n\n\t/* mac80211 doesn't allow mode changes while the device is up, so\n\t * take the device down, try to set the mode again, and bring the\n\t * device back up.\n\t */\n\twpa_printf(MSG_DEBUG, \"capwap: Try mode change after setting \"\n\t\t   \"interface down\");\n\tfor (i = 0; i < 10; i++) {\n\t\tint res;\n\t\tres = linux_set_iface_flags(drv->global->ioctl_sock,\n\t\t\t\t\t    bss->ifname, 0);\n\t\tif (res == -EACCES || res == -ENODEV)\n\t\t\tbreak;\n\t\tif (res == 0) {\n\t\t\t/* Try to set the mode again while the interface is\n\t\t\t * down */\n\t\t\tret = capwap_set_mode(drv, drv->ifindex, nlmode);\n\t\t\tif (ret == -EACCES)\n\t\t\t\tbreak;\n\t\t\tres = linux_set_iface_flags(drv->global->ioctl_sock,\n\t\t\t\t\t\t    bss->ifname, 1);\n\t\t\tif (res && !ret)\n\t\t\t\tret = -1;\n\t\t\telse if (ret != -EBUSY)\n\t\t\t\tbreak;\n\t\t} else\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to set \"\n\t\t\t\t   \"interface down\");\n\t\tos_sleep(0, 100000);\n\t}\n\n\tif (!ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Mode change succeeded while \"\n\t\t\t   \"interface is down\");\n\t\tdrv->nlmode = nlmode;\n\t\tdrv->ignore_if_down_event = 1;\n\t}\n\ndone:\n\n\tif (!ret && is_ap_interface(nlmode)) {\n\t\t/* Setup additional AP mode functionality if needed */\n\t\tif (!drv->no_monitor_iface_capab && drv->monitor_ifidx < 0 &&\n\t\t    capwap_create_monitor_interface(drv) &&\n\t\t    !drv->no_monitor_iface_capab)\n\t\t\treturn -1;\n\t} else if (!ret && !is_ap_interface(nlmode)) {\n\t\t/* Remove additional AP mode functionality */\n\t\tif (was_ap && drv->no_monitor_iface_capab)\n\t\t\twpa_driver_capwap_probe_req_report(bss, 0);\n\t\tcapwap_remove_monitor_interface(drv);\n\t\tbss->beacon_set = 0;\n\t}\n\n\tif (!ret && is_p2p_interface(drv->nlmode)) {\n\t\tcapwap_disable_11b_rates(drv, drv->ifindex, 1);\n\t\tdrv->disabled_11b_rates = 1;\n\t} else if (!ret && drv->disabled_11b_rates) {\n\t\tcapwap_disable_11b_rates(drv, drv->ifindex, 0);\n\t\tdrv->disabled_11b_rates = 0;\n\t}\n\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface mode change to %d \"\n\t\t\t   \"from %d failed\", nlmode, drv->nlmode);\n\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_get_capa(void *priv,\n\t\t\t\t       struct wpa_driver_capa *capa)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t1.wpa_driver_capwap_get_capa\\n\");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!drv->has_capability)\n\t\treturn -1;\n\tos_memcpy(capa, &drv->capa, sizeof(*capa));\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_set_operstate(void *priv, int state)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\twpa_printf(MSG_DEBUG, \"%s: operstate %d->%d (%s)\",\n\t\t   __func__, drv->operstate, state, state ? \"UP\" : \"DORMANT\");\n\tdrv->operstate = state;\n\treturn netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,\n\t\t\t\t      state ? IF_OPER_UP : IF_OPER_DORMANT);\n}\n\n\nstatic int wpa_driver_capwap_set_supp_port(void *priv, int authorized)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tstruct nl80211_sta_flag_update upd;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);\n\n\tos_memset(&upd, 0, sizeof(upd));\n\tupd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);\n\tif (authorized)\n\t\tupd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);\n\tNLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\n/* Set kernel driver on given frequency (MHz) */\nstatic int i802_set_freq(void *priv, struct hostapd_freq_params *freq)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t1.i802_set_freq \\n\");\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\treturn wpa_driver_capwap_set_freq(drv, freq->freq, freq->ht_enabled,\n\t\t\t\t\t   freq->sec_channel_offset);\n}\n\n\n#if defined(HOSTAPD) || defined(CONFIG_AP)\n\nstatic inline int min_int(int a, int b)\n{\n\tif (a < b)\n\t\treturn a;\n\treturn b;\n}\n\n\nstatic int get_key_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\t/*\n\t * TODO: validate the key index and mac address!\n\t * Otherwise, there's a race condition as soon as\n\t * the kernel starts sending key notifications.\n\t */\n\n\tif (tb[NL80211_ATTR_KEY_SEQ])\n\t\tmemcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),\n\t\t       min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));\n\treturn NL_SKIP;\n}\n\n\nstatic int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,\n\t\t\t   int idx, u8 *seq)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);\n\n\tif (addr)\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tNLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));\n\n\tmemset(seq, 0, 6);\n\n\treturn send_and_recv_msgs(drv, msg, get_key_handler, seq);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates,\n\t\t\t      int mode)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tu8 rates[NL80211_MAX_SUPP_RATES];\n\tu8 rates_len = 0;\n\tint i;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);\n\n\tfor (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++)\n\t\trates[rates_len++] = basic_rates[i] / 5;\n\n\tNLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\treturn -ENOBUFS;\n}\n\n\nstatic int i802_set_rts(void *priv, int rts)\n{\n\twpa_printf(MSG_DEBUG, \"> i802_set_rts %d \\n\",rts);\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\tu32 val;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tif (rts >= 2347)\n\t\tval = (u32) -1;\n\telse\n\t\tval = rts;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (!ret)\n\t\treturn 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to set RTS threshold %d: \"\n\t\t   \"%d (%s)\", rts, ret, strerror(-ret));\n\treturn ret;\n}\n\n\nstatic int i802_set_frag(void *priv, int frag)\n{\n\twpa_printf(MSG_DEBUG, \"> i802_set_frag  %d\\n\",frag);\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\tu32 val;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tif (frag >= 2346)\n\t\tval = (u32) -1;\n\telse\n\t\tval = frag;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (!ret)\n\t\treturn 0;\nnla_put_failure:\n\tnlmsg_free(msg);\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to set fragmentation threshold \"\n\t\t   \"%d: %d (%s)\", frag, ret, strerror(-ret));\n\treturn ret;\n}\n\n\nstatic int i802_flush(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);\n\n\t/*\n\t * XXX: FIX! this needs to flush all VLANs too\n\t */\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int get_sta_handler(struct nl_msg *msg, void *arg)\n{\n\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tstruct hostap_sta_driver_data *data = arg;\n\tstruct nlattr *stats[NL80211_STA_INFO_MAX + 1];\n\tstatic struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {\n\t\t[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },\n\t\t[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },\n\t};\n\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\n\t/*\n\t * TODO: validate the interface and mac address!\n\t * Otherwise, there's a race condition as soon as\n\t * the kernel starts sending station notifications.\n\t */\n\n\tif (!tb[NL80211_ATTR_STA_INFO]) {\n\t\twpa_printf(MSG_DEBUG, \"sta stats missing!\");\n\t\treturn NL_SKIP;\n\t}\n\tif (nla_parse_nested(stats, NL80211_STA_INFO_MAX,\n\t\t\t     tb[NL80211_ATTR_STA_INFO],\n\t\t\t     stats_policy)) {\n\t\twpa_printf(MSG_DEBUG, \"failed to parse nested attributes!\");\n\t\treturn NL_SKIP;\n\t}\n\n\tif (stats[NL80211_STA_INFO_INACTIVE_TIME])\n\t\tdata->inactive_msec =\n\t\t\tnla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);\n\tif (stats[NL80211_STA_INFO_RX_BYTES])\n\t\tdata->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);\n\tif (stats[NL80211_STA_INFO_TX_BYTES])\n\t\tdata->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);\n\tif (stats[NL80211_STA_INFO_RX_PACKETS])\n\t\tdata->rx_packets =\n\t\t\tnla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);\n\tif (stats[NL80211_STA_INFO_TX_PACKETS])\n\t\tdata->tx_packets =\n\t\t\tnla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);\n\n\treturn NL_SKIP;\n}\n\nstatic int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,\n\t\t\t      const u8 *addr)\n{\n\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tos_memset(data, 0, sizeof(*data));\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);\n\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\treturn send_and_recv_msgs(drv, msg, get_sta_handler, data);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int i802_set_tx_queue_params(void *priv, int queue, int aifs,\n\t\t\t\t    int cw_min, int cw_max, int burst_time)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tstruct nlattr *txq, *params;\n\n\tflush_SET_TXQ_handle(generic_wtp_info.fd_ipc, drv->ctx);\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\n\ttxq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);\n\tif (!txq)\n\t\tgoto nla_put_failure;\n\n\t/* We are only sending parameters for a single TXQ at a time */\n\tparams = nla_nest_start(msg, 1);\n\tif (!params)\n\t\tgoto nla_put_failure;\n\n\tswitch (queue) {\n\tcase 0:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO);\n\t\tbreak;\n\tcase 1:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI);\n\t\tbreak;\n\tcase 2:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE);\n\t\tbreak;\n\tcase 3:\n\t\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK);\n\t\tbreak;\n\t}\n\t/* Burst time is configured in units of 0.1 msec and TXOP parameter in\n\t * 32 usec, so need to convert the value here. */\n\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32);\n\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);\n\tNLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);\n\tNLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);\n\n\tnla_nest_end(msg, params);\n\n\tnla_nest_end(msg, txq);\n\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n\t\treturn 0;\n\tmsg = NULL;\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int i802_set_sta_vlan(void *priv, const u8 *addr,\n\t\t\t     const char *ifname, int vlan_id)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret = -ENOBUFS;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,\n\t\t    if_nametoindex(bss->ifname));\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);\n\tNLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN,\n\t\t    if_nametoindex(ifname));\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: NL80211_ATTR_STA_VLAN (addr=\"\n\t\t\t   MACSTR \" ifname=%s vlan_id=%d) failed: %d (%s)\",\n\t\t\t   MAC2STR(addr), ifname, vlan_id, ret,\n\t\t\t   strerror(-ret));\n\t}\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int i802_get_inact_sec(void *priv, const u8 *addr)\n{\n\n\tstruct hostap_sta_driver_data data;\n\tint ret;\n\n\tdata.inactive_msec = (unsigned long) -1;\n\tret = i802_read_sta_data(priv, &data, addr);\n\tif (ret || data.inactive_msec == (unsigned long) -1)\n\t\treturn -1;\n\treturn data.inactive_msec / 1000;\n}\n\n\nstatic int i802_sta_clear_stats(void *priv, const u8 *addr)\n{\n#if 0\n\t/* TODO */\n#endif\n\treturn 0;\n}\n\n\nstatic int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,\n\t\t\t   int reason)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t\t\t\t\t1.i802_sta_deauth \\n\");\n\n\tstruct i802_bss *bss = priv;\n\tstruct ieee80211_mgmt mgmt;\n\n\tmemset(&mgmt, 0, sizeof(mgmt));\n\tmgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,\n\t\t\t\t\t  WLAN_FC_STYPE_DEAUTH);\n\tmemcpy(mgmt.da, addr, ETH_ALEN);\n\tmemcpy(mgmt.sa, own_addr, ETH_ALEN);\n\tmemcpy(mgmt.bssid, own_addr, ETH_ALEN);\n\tmgmt.u.deauth.reason_code = host_to_le16(reason);\n\treturn wpa_driver_capwap_send_mlme(bss, (u8 *) &mgmt,\n\t\t\t\t\t    IEEE80211_HDRLEN +\n\t\t\t\t\t    sizeof(mgmt.u.deauth));\n}\n\n\nstatic int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,\n\t\t\t     int reason)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct ieee80211_mgmt mgmt;\n\n\tmemset(&mgmt, 0, sizeof(mgmt));\n\tmgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,\n\t\t\t\t\t  WLAN_FC_STYPE_DISASSOC);\n\tmemcpy(mgmt.da, addr, ETH_ALEN);\n\tmemcpy(mgmt.sa, own_addr, ETH_ALEN);\n\tmemcpy(mgmt.bssid, own_addr, ETH_ALEN);\n\tmgmt.u.disassoc.reason_code = host_to_le16(reason);\n\treturn wpa_driver_capwap_send_mlme(bss, (u8 *) &mgmt,\n\t\t\t\t\t    IEEE80211_HDRLEN +\n\t\t\t\t\t    sizeof(mgmt.u.disassoc));\n}\n\n#endif /* HOSTAPD || CONFIG_AP */\n\n#ifdef HOSTAPD\n\nstatic void add_ifidx(struct wpa_driver_capwap_data *drv, int ifidx){\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t\t3.add_ifidx\\n\");\n\tint i;\n\tint *old;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Add own interface ifindex %d\",\n\t\t   ifidx);\n\tfor (i = 0; i < drv->num_if_indices; i++) {\n\t\tif (drv->if_indices[i] == 0) {\n\t\t\tdrv->if_indices[i] = ifidx;\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (drv->if_indices != drv->default_if_indices)\n\t\told = drv->if_indices;\n\telse\n\t\told = NULL;\n\n\tdrv->if_indices = os_realloc(old,\n\t\t\t\t     sizeof(int) * (drv->num_if_indices + 1));\n\tif (!drv->if_indices) {\n\t\tif (!old)\n\t\t\tdrv->if_indices = drv->default_if_indices;\n\t\telse\n\t\t\tdrv->if_indices = old;\n\t\twpa_printf(MSG_ERROR, \"Failed to reallocate memory for \"\n\t\t\t   \"interfaces\");\n\t\twpa_printf(MSG_ERROR, \"Ignoring EAPOL on interface %d\", ifidx);\n\t\treturn;\n\t} else if (!old)\n\t\tos_memcpy(drv->if_indices, drv->default_if_indices,\n\t\t\t  sizeof(drv->default_if_indices));\n\tdrv->if_indices[drv->num_if_indices] = ifidx;\n\tdrv->num_if_indices++;\n}\n\n\nstatic void del_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n\tint i;\n\n\tfor (i = 0; i < drv->num_if_indices; i++) {\n\t\tif (drv->if_indices[i] == ifidx) {\n\t\t\tdrv->if_indices[i] = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\nstatic int have_ifidx(struct wpa_driver_capwap_data *drv, int ifidx)\n{\n\tint i;\n\n\tfor (i = 0; i < drv->num_if_indices; i++)\n\t\tif (drv->if_indices[i] == ifidx)\n\t\t\treturn 1;\n\n\treturn 0;\n}\n\n\nstatic int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,\n                            const char *bridge_ifname)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tchar name[IFNAMSIZ + 1];\n\n\tos_snprintf(name, sizeof(name), \"%s.sta%d\", bss->ifname, aid);\n\twpa_printf(MSG_DEBUG, \"capwap: Set WDS STA addr=\" MACSTR\n\t\t   \" aid=%d val=%d name=%s\", MAC2STR(addr), aid, val, name);\n\tif (val) {\n\t\tif (!if_nametoindex(name)) {\n\t\t\tif (capwap_create_iface(drv, name,\n\t\t\t\t\t\t NL80211_IFTYPE_AP_VLAN,\n\t\t\t\t\t\t NULL, 1) < 0)\n\t\t\t\treturn -1;\n\t\t\tif (bridge_ifname &&\n\t\t\t    linux_br_add_if(drv->global->ioctl_sock,\n\t\t\t\t\t    bridge_ifname, name) < 0)\n\t\t\t\treturn -1;\n\t\t}\n\t\tlinux_set_iface_flags(drv->global->ioctl_sock, name, 1);\n\t\treturn i802_set_sta_vlan(priv, addr, name, 0);\n\t} else {\n\t\ti802_set_sta_vlan(priv, addr, bss->ifname, 0);\n\t\treturn wpa_driver_capwap_if_remove(priv, WPA_IF_AP_VLAN,\n\t\t\t\t\t\t    name);\n\t}\n}\n\n\nstatic void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)\n{\n\n\n\n\n\tstruct wpa_driver_capwap_data *drv = eloop_ctx;\n\tstruct sockaddr_ll lladdr;\n\tunsigned char buf[3000];\n\tint len;\n\n\n\n\tsocklen_t fromlen = sizeof(lladdr);\n\n\tlen = recvfrom(sock, buf, sizeof(buf), 0,\n\t\t       (struct sockaddr *)&lladdr, &fromlen);\n\n\n    if (len < 0) {\n\t\tperror(\"recv\");\n\t\treturn;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"%d, %d\", len,have_ifidx(drv, lladdr.sll_ifindex));\n\tint i; wpa_printf(MSG_DEBUG, \"  EAPOL MAC: \");\n\tfor(i=0; i<6; i++ )wpa_printf(MSG_DEBUG, \"%02X \",lladdr.sll_addr[i]);printf(\"\\n\");\n\n\n    u8 outbuf_8022[BUFFER_SIZE];\n    u8 outbuf_80211[BUFFER_SIZE];\n    int outlen_8022 = add_8022_header(buf, len, outbuf_8022);\n    int outlen_80211 = add_80211_Data_header(generic_wtp_info.own_mac_addr, lladdr.sll_addr, generic_wtp_info.own_mac_addr, 1, 0, outbuf_8022, outlen_8022, outbuf_80211);\n\n   wpa_printf(MSG_DEBUG, \"EAPOL Data Frame 5 (%d)\\n\",outlen_80211);\n\n   // flush_pcap(outlen_80211,outbuf_80211,WTP_LOG);\n\n\n\t\tipc_send_80211_to_ac(generic_wtp_info.fd_ipc, outbuf_80211, outlen_80211);\n\t\t//WTP_handle_send_data_to_AC(outbuf_80211, outlen_80211);\n\t\treturn;\n\n\n\tif (have_ifidx(drv, lladdr.sll_ifindex))\n\t\tdrv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);\n}\n\n\nstatic int i802_check_bridge(struct wpa_driver_capwap_data *drv,\n\t\t\t     struct i802_bss *bss,\n\t\t\t     const char *brname, const char *ifname)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t\t7.i802_check_bridge\\n\");\n\tint ifindex;\n\tchar in_br[IFNAMSIZ];\n\n\tos_strlcpy(bss->brname, brname, IFNAMSIZ);\n\tifindex = if_nametoindex(brname);\n\tif (ifindex == 0) {\n\t\t/*\n\t\t * Bridge was configured, but the bridge device does\n\t\t * not exist. Try to add it now.\n\t\t */\n\t\tif (linux_br_add(drv->global->ioctl_sock, brname) < 0) {\n\t\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add the \"\n\t\t\t\t   \"bridge interface %s: %s\",\n\t\t\t\t   brname, strerror(errno));\n\t\t\treturn -1;\n\t\t}\n\t\tbss->added_bridge = 1;\n\t\tadd_ifidx(drv, if_nametoindex(brname));\n\t}\n\n\tif (linux_br_get(in_br, ifname) == 0) {\n\t\tif (os_strcmp(in_br, brname) == 0)\n\t\t\treturn 0; /* already in the bridge */\n\n\t\twpa_printf(MSG_DEBUG, \"capwap: Removing interface %s from \"\n\t\t\t   \"bridge %s\", ifname, in_br);\n\t\tif (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <\n\t\t    0) {\n\t\t\twpa_printf(MSG_ERROR, \"capwap: Failed to \"\n\t\t\t\t   \"remove interface %s from bridge \"\n\t\t\t\t   \"%s: %s\",\n\t\t\t\t   ifname, brname, strerror(errno));\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Adding interface %s into bridge %s\",\n\t\t   ifname, brname);\n\tif (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add interface %s \"\n\t\t\t   \"into bridge %s: %s\",\n\t\t\t   ifname, brname, strerror(errno));\n\t\treturn -1;\n\t}\n\tbss->added_if_into_bridge = 1;\n\n\treturn 0;\n}\n\nvoid AC_popu_capa_info(struct i802_bss *bss, unsigned char *mac_addr)\n{\n\tstruct hostapd_hw_modes *tmp_modes;\n\tu16 num_modes1, flags1;\n\ttmp_modes = wpa_driver_capwap_get_hw_feature_data(bss, &num_modes1, &flags1);\n\tif(tmp_modes == NULL){\n\t\twpa_printf(MSG_DEBUG, \"NULL mm\\n\");\n\t\texit(1);\n\t}\n\n\tint cnt_indx;\n\tfor(cnt_indx=0; cnt_indx<21; cnt_indx++)\n\t\tac_params.capa_buf[cnt_indx] = 0;\n\n\tfor(cnt_indx=0; cnt_indx<num_modes1; cnt_indx++) {\n\t\tstruct hostapd_hw_modes *fe = &tmp_modes[cnt_indx];\n\t\tac_params.capa_buf[10] = fe->channels[0].chan;\n\t\tac_params.capa_buf[12] = fe->num_channels;\n\t\tac_params.capa_buf[14] = fe->channels[0].max_tx_power;\n\n\t\tint kk;\n\t\tfor(kk=0; kk<fe->num_rates && kk<8 ;kk++) {\n\t\t\tint tmp_sup_rate = (unsigned char)(fe->rates[kk] / 5);\n\t\t\tif(fe->mode == HOSTAPD_MODE_IEEE80211B) tmp_sup_rate |= 0x80;\n\t\t\tif(tmp_sup_rate > ac_params.capa_buf[kk]) ac_params.capa_buf[kk] = tmp_sup_rate;\n\t\t}\n\n\t\tif(fe->mode == HOSTAPD_MODE_IEEE80211B ) ac_params.capa_buf[8] |= 1;\n\t\tif(fe->mode == HOSTAPD_MODE_IEEE80211A ) ac_params.capa_buf[8] |= 2;\n\t\tif(fe->mode == HOSTAPD_MODE_IEEE80211G ) ac_params.capa_buf[8] |= 4;\n\t}\n\tmemcpy(ac_params.capa_buf + 15, bss->drv->addr, 6);\n}\n\nstatic void *i802_init(struct hostapd_data *hapd,\n\t\t       struct wpa_init_params *params)\n{\n\twpa_printf(MSG_DEBUG, \"\t\t\t\t1.i802_init\\n\");\n\n\tstruct wpa_driver_capwap_data *drv;\n\tstruct i802_bss *bss;\n\tsize_t i;\n\tchar brname[IFNAMSIZ];\n\tint ifindex, br_ifindex;\n\tint br_added = 0;\n\n\tbss = wpa_driver_capwap_init(hapd, params->ifname,\n\t\t\t\t      params->global_priv);\n\n\tif (bss == NULL)\n\t\treturn NULL;\n\n\tdrv = bss->drv;\n\tdrv->nlmode = NL80211_IFTYPE_AP;\n\tdrv->eapol_sock = -1;\n\n\tif (linux_br_get(brname, params->ifname) == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Interface %s is in bridge %s\",\n\t\t\t   params->ifname, brname);\n\t\tbr_ifindex = if_nametoindex(brname);\n\t} else {\n\t\tbrname[0] = '\\0';\n\t\tbr_ifindex = 0;\n\t}\n\n\tdrv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);\n\tdrv->if_indices = drv->default_if_indices;\n\tfor (i = 0; i < params->num_bridge; i++) {\n\t\tif (params->bridge[i]) {\n\t\t\tifindex = if_nametoindex(params->bridge[i]);\n\t\t\tif (ifindex)\n\t\t\t\tadd_ifidx(drv, ifindex);\n\t\t\tif (ifindex == br_ifindex)\n\t\t\t\tbr_added = 1;\n\t\t}\n\t}\n\n\tif (!br_added && br_ifindex &&\n\t    (params->num_bridge == 0 || !params->bridge[0]))\n\t\tadd_ifidx(drv, br_ifindex);\n\n\t/* start listening for EAPOL on the default AP interface */\n\tadd_ifidx(drv, drv->ifindex);\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0))\n\t\tgoto failed;\n\n\tif (params->bssid) {\n\t\tif (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t\t       params->bssid))\n\t\t\tgoto failed;\n\t}\n\n\tif (wpa_driver_capwap_set_mode(bss, drv->nlmode)) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to set interface %s \"\n\t\t\t   \"into AP mode\", bss->ifname);\n\t\tgoto failed;\n\t}\n\n\n\tif (params->num_bridge && params->bridge[0] &&\n\t    i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)\n\t\tgoto failed;\n\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1))\n\t\tgoto failed;\n\n\tdrv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));\n\tif (drv->eapol_sock < 0) {\n\t\tperror(\"socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)\");\n\t\tgoto failed;\n\t}\n\n\n\n\tif (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))\n\t{\n\t\twpa_printf(MSG_DEBUG, \"Could not register read socket for eapol\\n\");\n\t\tgoto failed;\n\t}\n\n\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t       params->own_addr))\n\t\tgoto failed;\n\n/* capwap FIXME: not defined\n\twpa_printf(MSG_DEBUG, \"iFace: %s  TapInterface: %s \\n\",params->ifname,params->tap);\n*/\n\n/* capwap FIXME: unused\n\tgeneric_wtp_info.wlan_interface = params->ifname;\n\tgeneric_wtp_info.tap_interface = params->tap;\n\tgeneric_wtp_info.br_interface = params->br_name;\n*/\n\n\tAC_popu_capa_info(bss, params->own_addr);\n\n\twpa_printf(MSG_DEBUG, \"%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\\n\",\n\t\t   ac_params.capa_buf[0],\n\t\t   ac_params.capa_buf[1],\n\t\t   ac_params.capa_buf[2],\n\t\t   ac_params.capa_buf[3],\n\t\t   ac_params.capa_buf[4],\n\t\t   ac_params.capa_buf[5],\n\t\t   ac_params.capa_buf[6],\n\t\t   ac_params.capa_buf[7],\n\t\t   ac_params.capa_buf[8],\n\t\t   ac_params.capa_buf[9],\n\t\t   ac_params.capa_buf[10],\n\t\t   ac_params.capa_buf[11],\n\t\t   ac_params.capa_buf[12],\n\t\t   ac_params.capa_buf[13],\n\t\t   ac_params.capa_buf[14],\n\t\t   ac_params.capa_buf[15],\n\t\t   ac_params.capa_buf[16],\n\t\t   ac_params.capa_buf[17],\n\t\t   ac_params.capa_buf[18],\n\t\t   ac_params.capa_buf[19],\n\t\t   ac_params.capa_buf[20]);\n\n\tgeneric_wtp_info.fd_ipc = start_ipc(drv->ctx,\n\t\t\t\t\t    ac_params.ssid,\n\t\t\t\t\t    &(ac_params.ssid_len),\n\t\t\t\t\t    WTP_inject_frame_in_air,\n\t\t\t\t\t    ac_params.capa_buf);\n\n\tmemcpy(params->ssid, ac_params.ssid, ac_params.ssid_len);\n\tparams->ssid_len = ac_params.ssid_len;\n\n\tif(generic_wtp_info.fd_ipc<=0) {\n\t\twpa_printf(MSG_ERROR, \"Error: start_ipc\");\n\t\treturn NULL;\n\t}\n\n\treturn bss;\n\nfailed:\n\twpa_driver_capwap_deinit(bss);\n\treturn NULL;\n}\n\n\nstatic void i802_deinit(void *priv)\n{\n\twpa_printf(MSG_DEBUG, \"> i802_deinit \\n\");\n\n\tend_ipc(generic_wtp_info.fd_ipc);\n\twpa_driver_capwap_deinit(priv);\n}\n\n#endif /* HOSTAPD */\n\n\nstatic enum nl80211_iftype wpa_driver_capwap_if_type(\n\tenum wpa_driver_if_type type)\n{\n\tswitch (type) {\n\tcase WPA_IF_STATION:\n\t\treturn NL80211_IFTYPE_STATION;\n\tcase WPA_IF_P2P_CLIENT:\n\tcase WPA_IF_P2P_GROUP:\n\t\treturn NL80211_IFTYPE_P2P_CLIENT;\n\tcase WPA_IF_AP_VLAN:\n\t\treturn NL80211_IFTYPE_AP_VLAN;\n\tcase WPA_IF_AP_BSS:\n\t\treturn NL80211_IFTYPE_AP;\n\tcase WPA_IF_P2P_GO:\n\t\treturn NL80211_IFTYPE_P2P_GO;\n\t}\n\treturn -1;\n}\n\n\n#ifdef CONFIG_P2P\n\nstatic int capwap_addr_in_use(struct capwap_global *global, const u8 *addr)\n{\n\tstruct wpa_driver_capwap_data *drv;\n\tdl_list_for_each(drv, &global->interfaces,\n\t\t\t struct wpa_driver_capwap_data, list) {\n\t\tif (os_memcmp(addr, drv->addr, ETH_ALEN) == 0)\n\t\t\treturn 1;\n\t}\n\treturn 0;\n}\n\n\nstatic int capwap_p2p_interface_addr(struct wpa_driver_capwap_data *drv,\n\t\t\t\t      u8 *new_addr)\n{\n\tunsigned int idx;\n\n\tif (!drv->global)\n\t\treturn -1;\n\n\tos_memcpy(new_addr, drv->addr, ETH_ALEN);\n\tfor (idx = 0; idx < 64; idx++) {\n\t\tnew_addr[0] = drv->addr[0] | 0x02;\n\t\tnew_addr[0] ^= idx << 2;\n\t\tif (!capwap_addr_in_use(drv->global, new_addr))\n\t\t\tbreak;\n\t}\n\tif (idx == 64)\n\t\treturn -1;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Assigned new P2P Interface Address \"\n\t\t   MACSTR, MAC2STR(new_addr));\n\n\treturn 0;\n}\n\n#endif /* CONFIG_P2P */\n\n\nstatic int wpa_driver_capwap_if_add(void *priv, enum wpa_driver_if_type type,\n\t\t\t\t     const char *ifname, const u8 *addr,\n\t\t\t\t     void *bss_ctx, void **drv_priv,\n\t\t\t\t     char *force_ifname, u8 *if_addr,\n\t\t\t\t     const char *bridge)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ifidx;\n#ifdef HOSTAPD\n\tstruct i802_bss *new_bss = NULL;\n\n\tif (type == WPA_IF_AP_BSS) {\n\t\tnew_bss = os_zalloc(sizeof(*new_bss));\n\t\tif (new_bss == NULL)\n\t\t\treturn -1;\n\t}\n#endif /* HOSTAPD */\n\n\tif (addr)\n\t\tos_memcpy(if_addr, addr, ETH_ALEN);\n\tifidx = capwap_create_iface(drv, ifname,\n\t\t\t\t     wpa_driver_capwap_if_type(type), addr,\n\t\t\t\t     0);\n\tif (ifidx < 0) {\n#ifdef HOSTAPD\n\t\tos_free(new_bss);\n#endif /* HOSTAPD */\n\t\treturn -1;\n\t}\n\n\tif (!addr &&\n\t    linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t       if_addr) < 0) {\n\t\tcapwap_remove_iface(drv, ifidx);\n\t\treturn -1;\n\t}\n\n#ifdef CONFIG_P2P\n\tif (!addr &&\n\t    (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||\n\t     type == WPA_IF_P2P_GO)) {\n\t\t/* Enforce unique P2P Interface Address */\n\t\tu8 new_addr[ETH_ALEN], own_addr[ETH_ALEN];\n\n\t\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t\t       own_addr) < 0 ||\n\t\t    linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,\n\t\t\t\t       new_addr) < 0) {\n\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\treturn -1;\n\t\t}\n\t\tif (os_memcmp(own_addr, new_addr, ETH_ALEN) == 0) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Allocate new address \"\n\t\t\t\t   \"for P2P group interface\");\n\t\t\tif (capwap_p2p_interface_addr(drv, new_addr) < 0) {\n\t\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,\n\t\t\t\t\t       new_addr) < 0) {\n\t\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t\tos_memcpy(if_addr, new_addr, ETH_ALEN);\n\t}\n#endif /* CONFIG_P2P */\n\n#ifdef HOSTAPD\n\tif (bridge &&\n\t    i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Failed to add the new \"\n\t\t\t   \"interface %s to a bridge %s\", ifname, bridge);\n\t\tcapwap_remove_iface(drv, ifidx);\n\t\tos_free(new_bss);\n\t\treturn -1;\n\t}\n\n\tif (type == WPA_IF_AP_BSS) {\n\t\tif (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))\n\t\t{\n\t\t\tcapwap_remove_iface(drv, ifidx);\n\t\t\tos_free(new_bss);\n\t\t\treturn -1;\n\t\t}\n\t\tos_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);\n\t\tnew_bss->ifindex = ifidx;\n\t\tnew_bss->drv = drv;\n\t\tnew_bss->next = drv->first_bss.next;\n\t\tdrv->first_bss.next = new_bss;\n\t\tif (drv_priv)\n\t\t\t*drv_priv = new_bss;\n\t}\n#endif /* HOSTAPD */\n\n\tif (drv->global)\n\t\tdrv->global->if_add_ifindex = ifidx;\n\n\treturn 0;\n}\n\n\nstatic int wpa_driver_capwap_if_remove(void *priv,\n\t\t\t\t\tenum wpa_driver_if_type type,\n\t\t\t\t\tconst char *ifname)\n{\n \tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ifindex = if_nametoindex(ifname);\n\n\twpa_printf(MSG_DEBUG, \"capwap: %s(type=%d ifname=%s) ifindex=%d\",\n\t\t   __func__, type, ifname, ifindex);\n\tif (ifindex <= 0)\n\t\treturn -1;\n\n#ifdef HOSTAPD\n\tif (bss->added_if_into_bridge) {\n\t\tif (linux_br_del_if(drv->global->ioctl_sock, bss->brname,\n\t\t\t\t    bss->ifname) < 0)\n\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n\t\t\t\t   \"interface %s from bridge %s: %s\",\n\t\t\t\t   bss->ifname, bss->brname, strerror(errno));\n\t}\n\tif (bss->added_bridge) {\n\t\tif (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)\n\t\t\twpa_printf(MSG_INFO, \"capwap: Failed to remove \"\n\t\t\t\t   \"bridge %s: %s\",\n\t\t\t\t   bss->brname, strerror(errno));\n\t}\n#endif /* HOSTAPD */\n\n\tcapwap_remove_iface(drv, ifindex);\n\n#ifdef HOSTAPD\n\tif (type != WPA_IF_AP_BSS)\n\t\treturn 0;\n\n\tif (bss != &drv->first_bss) {\n\t\tstruct i802_bss *tbss;\n\n\t\tfor (tbss = &drv->first_bss; tbss; tbss = tbss->next) {\n\t\t\tif (tbss->next == bss) {\n\t\t\t\ttbss->next = bss->next;\n\t\t\t\tos_free(bss);\n\t\t\t\tbss = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (bss)\n\t\t\twpa_printf(MSG_INFO, \"capwap: %s - could not find \"\n\t\t\t\t   \"BSS %p in the list\", __func__, bss);\n\t}\n#endif /* HOSTAPD */\n\n\treturn 0;\n}\n\n\nstatic int cookie_handler(struct nl_msg *msg, void *arg)\n{\n\tstruct nlattr *tb[NL80211_ATTR_MAX + 1];\n\tstruct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));\n\tu64 *cookie = arg;\n\tnla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),\n\t\t  genlmsg_attrlen(gnlh, 0), NULL);\n\tif (tb[NL80211_ATTR_COOKIE])\n\t\t*cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);\n\treturn NL_SKIP;\n}\n\n\nstatic int capwap_send_frame_cmd(struct wpa_driver_capwap_data *drv,\n\t\t\t\t  unsigned int freq, unsigned int wait,\n\t\t\t\t  const u8 *buf, size_t buf_len,\n\t\t\t\t  u64 *cookie_out, int no_cck)\n{\n\tstruct nl_msg *msg;\n\tu64 cookie;\n\tint ret = -1;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_FRAME);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);\n\tif (wait)\n\t\tNLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);\n\tNLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);\n\tif (no_cck)\n\t\tNLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);\n\n\tNLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);\n\n\tcookie = 0;\n\tret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Frame command failed: ret=%d \"\n\t\t\t   \"(%s) (freq=%u wait=%u)\", ret, strerror(-ret),\n\t\t\t   freq, wait);\n\t\tgoto nla_put_failure;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Frame TX command accepted; \"\n\t\t   \"cookie 0x%llx\", (long long unsigned int) cookie);\n\n\tif (cookie_out)\n\t\t*cookie_out = cookie;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn ret;\n}\n\n\nstatic int wpa_driver_capwap_send_action(void *priv, unsigned int freq,\n\t\t\t\t\t  unsigned int wait_time,\n\t\t\t\t\t  const u8 *dst, const u8 *src,\n\t\t\t\t\t  const u8 *bssid,\n\t\t\t\t\t  const u8 *data, size_t data_len,\n\t\t\t\t\t  int no_cck)\n{\n \tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret = -1;\n\tu8 *buf;\n\tstruct ieee80211_hdr *hdr;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Send Action frame (ifindex=%d, \"\n\t\t   \"wait=%d ms no_cck=%d)\", drv->ifindex, wait_time, no_cck);\n\n\tbuf = os_zalloc(24 + data_len);\n\tif (buf == NULL)\n\t\treturn ret;\n\tos_memcpy(buf + 24, data, data_len);\n\thdr = (struct ieee80211_hdr *) buf;\n\thdr->frame_control =\n\t\tIEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);\n\tos_memcpy(hdr->addr1, dst, ETH_ALEN);\n\tos_memcpy(hdr->addr2, src, ETH_ALEN);\n\tos_memcpy(hdr->addr3, bssid, ETH_ALEN);\n\n\tif (is_ap_interface(drv->nlmode))\n\t\tret = wpa_driver_capwap_send_mlme(priv, buf, 24 + data_len);\n\telse\n\t\tret = capwap_send_frame_cmd(drv, freq, wait_time, buf,\n\t\t\t\t\t     24 + data_len,\n\t\t\t\t\t     &drv->send_action_cookie,\n\t\t\t\t\t     no_cck);\n\n\tos_free(buf);\n\treturn ret;\n}\n\n\nstatic void wpa_driver_capwap_send_action_cancel_wait(void *priv)\n{\n \tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret)\n\t\twpa_printf(MSG_DEBUG, \"capwap: wait cancel failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\n nla_put_failure:\n\tnlmsg_free(msg);\n}\n\n\nstatic int wpa_driver_capwap_remain_on_channel(void *priv, unsigned int freq,\n\t\t\t\t\t\tunsigned int duration)\n{\n \tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\tu64 cookie;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);\n\tNLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);\n\n\tcookie = 0;\n\tret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);\n\tmsg = NULL;\n\tif (ret == 0) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Remain-on-channel cookie \"\n\t\t\t   \"0x%llx for freq=%u MHz duration=%u\",\n\t\t\t   (long long unsigned int) cookie, freq, duration);\n\t\tdrv->remain_on_chan_cookie = cookie;\n\t\tdrv->pending_remain_on_chan = 1;\n\t\treturn 0;\n\t}\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to request remain-on-channel \"\n\t\t   \"(freq=%d duration=%u): %d (%s)\",\n\t\t   freq, duration, ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int wpa_driver_capwap_cancel_remain_on_channel(void *priv)\n{\n \tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tint ret;\n\n\tif (!drv->pending_remain_on_chan) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: No pending remain-on-channel \"\n\t\t\t   \"to cancel\");\n\t\treturn -1;\n\t}\n\n\twpa_printf(MSG_DEBUG, \"capwap: Cancel remain-on-channel with cookie \"\n\t\t   \"0x%llx\",\n\t\t   (long long unsigned int) drv->remain_on_chan_cookie);\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret == 0)\n\t\treturn 0;\n\twpa_printf(MSG_DEBUG, \"capwap: Failed to cancel remain-on-channel: \"\n\t\t   \"%d (%s)\", ret, strerror(-ret));\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int wpa_driver_capwap_probe_req_report(void *priv, int report)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\tif (!report) {\n\t\tif (drv->nl_preq.handle && drv->no_monitor_iface_capab &&\n\t\t    is_ap_interface(drv->nlmode)) {\n\t\t\t/*\n\t\t\t * Do not disable Probe Request reporting that was\n\t\t\t * enabled in capwap_setup_ap().\n\t\t\t */\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Skip disabling of \"\n\t\t\t\t   \"Probe Request reporting nl_preq=%p while \"\n\t\t\t\t   \"in AP mode\", drv->nl_preq.handle);\n\t\t} else if (drv->nl_preq.handle) {\n\t\t\twpa_printf(MSG_DEBUG, \"capwap: Disable Probe Request \"\n\t\t\t\t   \"reporting nl_preq=%p\", drv->nl_preq.handle);\n\t\t\teloop_unregister_read_sock(\n\t\t\t\tnl_socket_get_fd(drv->nl_preq.handle));\n\t\t\tnl_destroy_handles(&drv->nl_preq);\n\t\t}\n\t\treturn 0;\n\t}\n\n\tif (drv->nl_preq.handle) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Probe Request reporting \"\n\t\t\t   \"already on!\");\n\t\treturn 0;\n\t}\n\n\tif (nl_create_handles(&drv->nl_preq, drv->global->nl_cb, \"preq\"))\n\t\treturn -1;\n\n\tif (capwap_register_frame(drv, drv->nl_preq.handle,\n\t\t\t\t   (WLAN_FC_TYPE_MGMT << 2) |\n\t\t\t\t   (WLAN_FC_STYPE_PROBE_REQ << 4),\n\t\t\t\t   NULL, 0) < 0)\n\t\tgoto out_err;\n\n\teloop_register_read_sock(nl_socket_get_fd(drv->nl_preq.handle),\n\t\t\t\t wpa_driver_capwap_event_receive, drv,\n\t\t\t\t drv->nl_preq.handle);\n\n\treturn 0;\n\n out_err:\n\tnl_destroy_handles(&drv->nl_preq);\n\treturn -1;\n}\n\n\nstatic int capwap_disable_11b_rates(struct wpa_driver_capwap_data *drv,\n\t\t\t\t     int ifindex, int disabled)\n{\n\tstruct nl_msg *msg;\n\tstruct nlattr *bands, *band;\n\tint ret;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);\n\n\tbands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);\n\tif (!bands)\n\t\tgoto nla_put_failure;\n\n\t/*\n\t * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything\n\t * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS\n\t * rates. All 5 GHz rates are left enabled.\n\t */\n\tband = nla_nest_start(msg, NL80211_BAND_2GHZ);\n\tif (!band)\n\t\tgoto nla_put_failure;\n\tif (disabled) {\n\t\tNLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,\n\t\t\t\"\\x0c\\x12\\x18\\x24\\x30\\x48\\x60\\x6c\");\n\t}\n\tnla_nest_end(msg, band);\n\n\tnla_nest_end(msg, bands);\n\n\tret = send_and_recv_msgs(drv, msg, NULL, NULL);\n\tmsg = NULL;\n\tif (ret) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Set TX rates failed: ret=%d \"\n\t\t\t   \"(%s)\", ret, strerror(-ret));\n\t}\n\n\treturn ret;\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int wpa_driver_capwap_deinit_ap(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (!is_ap_interface(drv->nlmode))\n\t\treturn -1;\n\twpa_driver_capwap_del_beacon(drv);\n\treturn wpa_driver_capwap_set_mode(priv, NL80211_IFTYPE_STATION);\n}\n\n\nstatic int wpa_driver_capwap_deinit_p2p_cli(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)\n\t\treturn -1;\n\treturn wpa_driver_capwap_set_mode(priv, NL80211_IFTYPE_STATION);\n}\n\n\nstatic void wpa_driver_capwap_resume(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tif (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {\n\t\twpa_printf(MSG_DEBUG, \"capwap: Failed to set interface up on \"\n\t\t\t   \"resume event\");\n\t}\n}\n\n\nstatic int capwap_send_ft_action(void *priv, u8 action, const u8 *target_ap,\n\t\t\t\t  const u8 *ies, size_t ies_len)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint ret;\n\tu8 *data, *pos;\n\tsize_t data_len;\n\tu8 own_addr[ETH_ALEN];\n\n\tif (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,\n\t\t\t       own_addr) < 0)\n\t\treturn -1;\n\n\tif (action != 1) {\n\t\twpa_printf(MSG_ERROR, \"capwap: Unsupported send_ft_action \"\n\t\t\t   \"action %d\", action);\n\t\treturn -1;\n\t}\n\n\t/*\n\t * Action frame payload:\n\t * Category[1] = 6 (Fast BSS Transition)\n\t * Action[1] = 1 (Fast BSS Transition Request)\n\t * STA Address\n\t * Target AP Address\n\t * FT IEs\n\t */\n\n\tdata_len = 2 + 2 * ETH_ALEN + ies_len;\n\tdata = os_malloc(data_len);\n\tif (data == NULL)\n\t\treturn -1;\n\tpos = data;\n\t*pos++ = 0x06; /* FT Action category */\n\t*pos++ = action;\n\tos_memcpy(pos, own_addr, ETH_ALEN);\n\tpos += ETH_ALEN;\n\tos_memcpy(pos, target_ap, ETH_ALEN);\n\tpos += ETH_ALEN;\n\tos_memcpy(pos, ies, ies_len);\n\n\tret = wpa_driver_capwap_send_action(bss, drv->assoc_freq, 0,\n\t\t\t\t\t     drv->bssid, own_addr, drv->bssid,\n\t\t\t\t\t     data, data_len, 0);\n\tos_free(data);\n\n\treturn ret;\n}\n\n\nstatic int capwap_signal_monitor(void *priv, int threshold, int hysteresis)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg, *cqm = NULL;\n\n\twpa_printf(MSG_DEBUG, \"capwap: Signal monitor threshold=%d \"\n\t\t   \"hysteresis=%d\", threshold, hysteresis);\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -1;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n\n\tcqm = nlmsg_alloc();\n\tif (cqm == NULL)\n\t\treturn -1;\n\n\tNLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold);\n\tNLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);\n\tnla_put_nested(msg, NL80211_ATTR_CQM, cqm);\n\n\tif (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)\n\t\treturn 0;\n\tmsg = NULL;\n\nnla_put_failure:\n\tnlmsg_free(cqm);\n\tnlmsg_free(msg);\n\treturn -1;\n}\n\n\nstatic int capwap_signal_poll(void *priv, struct wpa_signal_info *si)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tint res;\n\n\tos_memset(si, 0, sizeof(*si));\n\tres = capwap_get_link_signal(drv, si);\n\tif (res != 0)\n\t\treturn res;\n\n\treturn capwap_get_link_noise(drv, si);\n}\n\n\nstatic int capwap_send_frame(void *priv, const u8 *data, size_t data_len,\n\t\t\t      int encrypt)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\treturn wpa_driver_capwap_send_frame(drv, data, data_len, encrypt);\n}\n\n\nstatic int capwap_set_param(void *priv, const char *param)\n{\n\n\twpa_printf(MSG_DEBUG, \"capwap: driver param='%s'\", param);\n\tif (param == NULL)\n\t\treturn 0;\n\n#ifdef CONFIG_P2P\n\tif (os_strstr(param, \"use_p2p_group_interface=1\")) {\n\t\tstruct i802_bss *bss = priv;\n\t\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\t\twpa_printf(MSG_DEBUG, \"capwap: Use separate P2P group \"\n\t\t\t   \"interface\");\n\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;\n\t\tdrv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;\n\t}\n#endif /* CONFIG_P2P */\n\n\treturn 0;\n}\n\n\nstatic void * capwap_global_init(void)\n{\n\twpa_printf(MSG_DEBUG,\"\t\t\t\t1.capwap_global_init\\n\");\n\tstruct capwap_global *global;\n\tstruct netlink_config *cfg;\n\n\tglobal = os_zalloc(sizeof(*global));\n\tif (global == NULL)\n\t\treturn NULL;\n\tglobal->ioctl_sock = -1;\n\tdl_list_init(&global->interfaces);\n\tglobal->if_add_ifindex = -1;\n\n\tcfg = os_zalloc(sizeof(*cfg));\n\tif (cfg == NULL)\n\t\tgoto err;\n\tcfg->ctx = global;\n\tcfg->newlink_cb = wpa_driver_capwap_event_rtm_newlink;\n\tcfg->dellink_cb = wpa_driver_capwap_event_rtm_dellink;\n\tglobal->netlink = netlink_init(cfg);\n\tif (global->netlink == NULL) {\n\t\tos_free(cfg);\n\t\tgoto err;\n\t}\n\tif (wpa_driver_capwap_init_nl_global(global) < 0)\n\t\tgoto err;\n\tglobal->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);\n\tif (global->ioctl_sock < 0) {\n\t\tperror(\"socket(PF_INET,SOCK_DGRAM)\");\n\t\tgoto err;\n\t}\n\n\treturn global;\n\nerr:\n\tcapwap_global_deinit(global);\n\treturn NULL;\n}\n\n\nstatic void capwap_global_deinit(void *priv)\n{\n\n\tstruct capwap_global *global = priv;\n\tif (global == NULL)\n\t\treturn;\n\tif (!dl_list_empty(&global->interfaces)) {\n\t\twpa_printf(MSG_ERROR, \"capwap: %u interface(s) remain at \"\n\t\t\t   \"capwap_global_deinit\",\n\t\t\t   dl_list_len(&global->interfaces));\n\t}\n\n\tif (global->netlink)\n\t\tnetlink_deinit(global->netlink);\n\n\tif (global->capwap)\n\t\tgenl_family_put(global->capwap);\n\tnl_destroy_handles(&global->nl);\n\n\tif (global->nl_cb)\n\t\tnl_cb_put(global->nl_cb);\n\n\tif (global->ioctl_sock >= 0)\n\t\tclose(global->ioctl_sock);\n\n\tos_free(global);\n}\n\n\nstatic const char * capwap_get_radio_name(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\treturn drv->phyname;\n}\n\n\nstatic int capwap_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,\n\t\t\t const u8 *pmkid)\n{\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(bss->drv, msg, 0, cmd);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));\n\tif (pmkid)\n\t\tNLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid);\n\tif (bssid)\n\t\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);\n\n\treturn send_and_recv_msgs(bss->drv, msg, NULL, NULL);\n nla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int capwap_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)\n{\n\n\tstruct i802_bss *bss = priv;\n\twpa_printf(MSG_DEBUG, \"capwap: Add PMKID for \" MACSTR, MAC2STR(bssid));\n\treturn capwap_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);\n}\n\n\nstatic int capwap_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)\n{\n\n\tstruct i802_bss *bss = priv;\n\twpa_printf(MSG_DEBUG, \"capwap: Delete PMKID for \" MACSTR,\n\t\t   MAC2STR(bssid));\n\treturn capwap_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);\n}\n\n\nstatic int capwap_flush_pmkid(void *priv)\n{\n\n\tstruct i802_bss *bss = priv;\n\twpa_printf(MSG_DEBUG, \"capwap: Flush PMKIDs\");\n\treturn capwap_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);\n}\n\n\nstatic void capwap_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,\n\t\t\t\t   const u8 *replay_ctr)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nlattr *replay_nested;\n\tstruct nl_msg *msg;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);\n\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);\n\n\treplay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);\n\tif (!replay_nested)\n\t\tgoto nla_put_failure;\n\n\tNLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);\n\tNLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);\n\tNLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,\n\t\treplay_ctr);\n\n\tnla_nest_end(msg, replay_nested);\n\n\tsend_and_recv_msgs(drv, msg, NULL, NULL);\n\treturn;\n nla_put_failure:\n\tnlmsg_free(msg);\n}\n\n\nstatic void capwap_poll_client(void *priv, const u8 *own_addr, const u8 *addr,\n\t\t\t\tint qos)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct {\n\t\tstruct ieee80211_hdr hdr;\n\t\tu16 qos_ctl;\n\t} STRUCT_PACKED nulldata;\n\tsize_t size;\n\n\t/* Send data frame to poll STA and check whether this frame is ACKed */\n\n\tos_memset(&nulldata, 0, sizeof(nulldata));\n\n\tif (qos) {\n\t\tnulldata.hdr.frame_control =\n\t\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA,\n\t\t\t\t     WLAN_FC_STYPE_QOS_NULL);\n\t\tsize = sizeof(nulldata);\n\t} else {\n\t\tnulldata.hdr.frame_control =\n\t\t\tIEEE80211_FC(WLAN_FC_TYPE_DATA,\n\t\t\t\t     WLAN_FC_STYPE_NULLFUNC);\n\t\tsize = sizeof(struct ieee80211_hdr);\n\t}\n\n\tnulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);\n\tos_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);\n\tos_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);\n\tos_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);\n\n\tif (wpa_driver_capwap_send_mlme(bss, (u8 *) &nulldata, size) < 0)\n\t\twpa_printf(MSG_DEBUG, \"capwap_send_null_frame: Failed to \"\n\t\t\t   \"send poll frame\");\n}\n\n\n#ifdef CONFIG_TDLS\n\nstatic int capwap_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,\n\t\t\t\t  u8 dialog_token, u16 status_code,\n\t\t\t\t  const u8 *buf, size_t len)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n\t\treturn -EOPNOTSUPP;\n\n\tif (!dst)\n\t\treturn -EINVAL;\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);\n\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);\n\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);\n\tNLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);\n\tNLA_PUT(msg, NL80211_ATTR_IE, len, buf);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n\nstatic int capwap_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)\n{\n\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\tstruct nl_msg *msg;\n\tenum capwap_tdls_operation capwap_oper;\n\n\tif (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))\n\t\treturn -EOPNOTSUPP;\n\n\tswitch (oper) {\n\tcase TDLS_DISCOVERY_REQ:\n\t\tcapwap_oper = NL80211_TDLS_DISCOVERY_REQ;\n\t\tbreak;\n\tcase TDLS_SETUP:\n\t\tcapwap_oper = NL80211_TDLS_SETUP;\n\t\tbreak;\n\tcase TDLS_TEARDOWN:\n\t\tcapwap_oper = NL80211_TDLS_TEARDOWN;\n\t\tbreak;\n\tcase TDLS_ENABLE_LINK:\n\t\tcapwap_oper = NL80211_TDLS_ENABLE_LINK;\n\t\tbreak;\n\tcase TDLS_DISABLE_LINK:\n\t\tcapwap_oper = NL80211_TDLS_DISABLE_LINK;\n\t\tbreak;\n\tcase TDLS_ENABLE:\n\t\treturn 0;\n\tcase TDLS_DISABLE:\n\t\treturn 0;\n\tdefault:\n\t\treturn -EINVAL;\n\t}\n\n\tmsg = nlmsg_alloc();\n\tif (!msg)\n\t\treturn -ENOMEM;\n\n\tcapwap_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);\n\tNLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, capwap_oper);\n\tNLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);\n\tNLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);\n\n\treturn send_and_recv_msgs(drv, msg, NULL, NULL);\n\nnla_put_failure:\n\tnlmsg_free(msg);\n\treturn -ENOBUFS;\n}\n\n#endif /* CONFIG TDLS */\n\nvoid WTP_inject_frame_in_air(void *priv, u8 *buf, int len)\n{\n\tstruct i802_bss *bss = priv;\n\tstruct wpa_driver_capwap_data *drv = bss->drv;\n\n\tint type = WTP_get_Type(buf ,len );\n\n\tif( type == WLAN_FC_TYPE_DATA){\n\t\tif( isEAPOL_Frame(buf, len) ){\n\t\t\twpa_printf(MSG_DEBUG, \"EAPOL Data Frame 2 (%d)\\n\",len);\n\t\t\twpa_driver_capwap_send_frame(drv,buf,len,0);\n\t\t} else\n\t\t\twpa_printf(MSG_DEBUG, \"ERROR Data Frame in hostapd WTP\");\n\t}\n\telse if( type == WLAN_FC_TYPE_MGMT ){\n\t\twpa_driver_capwap_send_frame(drv,buf,len,0);\n\t} else\n\t\twpa_printf(MSG_ERROR, \"ERROR: Received invalid/controlo 802.11 header type\");\n}\n\n\nconst struct wpa_driver_ops wpa_driver_capwap_wtp_ops = {\n\t.name = \"capwap_wtp\",\n\t.desc = \"Linux capwap/cfg80211\",\n\t.get_bssid = wpa_driver_capwap_get_bssid,\n\t.get_ssid = wpa_driver_capwap_get_ssid,\n\t.set_key = wpa_driver_capwap_set_key,\n\t.scan2 = wpa_driver_capwap_scan,\n\t.sched_scan = wpa_driver_capwap_sched_scan,\n\t.stop_sched_scan = wpa_driver_capwap_stop_sched_scan,\n\t.get_scan_results2 = wpa_driver_capwap_get_scan_results,\n\t.deauthenticate = wpa_driver_capwap_deauthenticate,\n\t.disassociate = wpa_driver_capwap_disassociate,\n\t.authenticate = wpa_driver_capwap_authenticate,\n\t.associate = wpa_driver_capwap_associate,\n\t.global_init = capwap_global_init,\n\t.global_deinit = capwap_global_deinit,\n\t.init2 = wpa_driver_capwap_init,\n\t.deinit = wpa_driver_capwap_deinit,\n\t.get_capa = wpa_driver_capwap_get_capa,\n\t.set_operstate = wpa_driver_capwap_set_operstate,\n\t.set_supp_port = wpa_driver_capwap_set_supp_port,\n\t.set_country = wpa_driver_capwap_set_country,\n\t.set_ap = wpa_driver_capwap_set_ap,\n\t.if_add = wpa_driver_capwap_if_add,\n\t.if_remove = wpa_driver_capwap_if_remove,\n\t.send_mlme = wpa_driver_capwap_send_mlme,\n\t.get_hw_feature_data = wpa_driver_capwap_get_hw_feature_data,\n\t.sta_add = wpa_driver_capwap_sta_add,\n\t.sta_remove = wpa_driver_capwap_sta_remove,\n\t.hapd_send_eapol = wpa_driver_capwap_hapd_send_eapol,\n\t.sta_set_flags = wpa_driver_capwap_sta_set_flags,\n\n#ifdef HOSTAPD\n\t.hapd_init = i802_init,\n\t.hapd_deinit = i802_deinit,\n\t.set_wds_sta = i802_set_wds_sta,\n#endif /* HOSTAPD */\n#if defined(HOSTAPD) || defined(CONFIG_AP)\n\t.get_seqnum = i802_get_seqnum,\n\t.flush = i802_flush,\n\t.read_sta_data = i802_read_sta_data,\n\t.get_inact_sec = i802_get_inact_sec,\n\t.sta_clear_stats = i802_sta_clear_stats,\n\t.set_rts = i802_set_rts,\n\t.set_frag = i802_set_frag,\n\t.set_tx_queue_params = i802_set_tx_queue_params,\n\t.set_sta_vlan = i802_set_sta_vlan,\n\t.set_rate_sets = i802_set_rate_sets,\n\t.sta_deauth = i802_sta_deauth,\n\t.sta_disassoc = i802_sta_disassoc,\n#endif /* HOSTAPD || CONFIG_AP */\n\t.set_freq = i802_set_freq,\n\t.send_action = wpa_driver_capwap_send_action,\n\t.send_action_cancel_wait = wpa_driver_capwap_send_action_cancel_wait,\n\t.remain_on_channel = wpa_driver_capwap_remain_on_channel,\n\t.cancel_remain_on_channel = wpa_driver_capwap_cancel_remain_on_channel,\n\t.probe_req_report = wpa_driver_capwap_probe_req_report,\n\t.deinit_ap = wpa_driver_capwap_deinit_ap,\n\t.deinit_p2p_cli = wpa_driver_capwap_deinit_p2p_cli,\n\t.resume = wpa_driver_capwap_resume,\n\t.send_ft_action = capwap_send_ft_action,\n\t.signal_monitor = capwap_signal_monitor,\n\t.signal_poll = capwap_signal_poll,\n\t.send_frame = capwap_send_frame,\n\t.set_param = capwap_set_param,\n\t.get_radio_name = capwap_get_radio_name,\n\t.add_pmkid = capwap_add_pmkid,\n\t.remove_pmkid = capwap_remove_pmkid,\n\t.flush_pmkid = capwap_flush_pmkid,\n\t.set_rekey_info = capwap_set_rekey_info,\n\t.poll_client = capwap_poll_client,\n#ifdef CONFIG_TDLS\n\t.send_tdls_mgmt = capwap_send_tdls_mgmt,\n\t.tdls_oper = capwap_tdls_oper,\n#endif /* CONFIG_TDLS */\n\t//.inject_frame_in_air = WTP_inject_frame_in_air,\n};\n"
  },
  {
    "path": "hostapd_wrapper/src/drivers/linux_ioctl_fake.c",
    "content": "/*\n * Linux ioctl helper functions for driver wrappers\n * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n\n#include \"utils/includes.h\"\n#include <sys/ioctl.h>\n#include <net/if.h>\n#include <net/if_arp.h>\n\n#include \"utils/common.h\"\n#include \"linux_ioctl_fake.h\"\n\n\n\nint linux_set_iface_flags(int sock, const char *ifname, int dev_up){\n\n\treturn 0;\n}\n\nint linux_iface_up(int sock, const char *ifname){\n\n\treturn 0;\n}\n\nint linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr){\n\n\tint i=2;\n\n\tif(i==0){ // TP-LINK (Atheros)\n\t\taddr[0]=0xB0;\n\t\taddr[1]=0x48;\n\t\taddr[2]=0x7A;\n\t\taddr[3]=0x93;\n\t\taddr[4]=0x90;\n\t\taddr[5]=0xF8;\n\n\t}else if(i==1){// D-Link\n\t\taddr[0]=0x28;\n\t\taddr[1]=0x10;\n\t\taddr[2]=0x7B;\n\t\taddr[3]=0x44;\n\t\taddr[4]=0xd0;\n\t\taddr[5]=0xB1;\n\n\t}else if(i==2){// TP-LINK (Atheros)\n\t\taddr[0]=0xAA;\n\t\taddr[1]=0xBB;\n\t\taddr[2]=0xCC;\n\t\taddr[3]=0xDD;\n\t\taddr[4]=0xEE;\n\t\taddr[5]=0xFF;\n\n\t}\n\n\treturn 0;\n}\n\nint linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr){\n\n\treturn 0;\n}\n\n\n#ifndef SIOCBRADDBR\n#define SIOCBRADDBR 0x89a0\n#endif\n#ifndef SIOCBRDELBR\n#define SIOCBRDELBR 0x89a1\n#endif\n#ifndef SIOCBRADDIF\n#define SIOCBRADDIF 0x89a2\n#endif\n#ifndef SIOCBRDELIF\n#define SIOCBRDELIF 0x89a3\n#endif\n\n\nint linux_br_add(int sock, const char *brname){\n\treturn 0;\n}\n\nint linux_br_del(int sock, const char *brname){\n\treturn 0;\n}\n\nint linux_br_add_if(int sock, const char *brname, const char *ifname){\n\treturn 0;\n}\n\nint linux_br_del_if(int sock, const char *brname, const char *ifname){\n\treturn 0;\n}\n\nint linux_br_get(char *brname, const char *ifname){\n\treturn 0;\n}\n\n\n"
  },
  {
    "path": "hostapd_wrapper/src/drivers/linux_ioctl_fake.h",
    "content": "/*\n * Linux ioctl helper functions for driver wrappers\n * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n#ifndef LINUX_IOCTL_H\n#define LINUX_IOCTL_H\n\nint linux_set_iface_flags(int sock, const char *ifname, int dev_up);\nint linux_iface_up(int sock, const char *ifname);\nint linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr);\nint linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr);\nint linux_br_add(int sock, const char *brname);\nint linux_br_del(int sock, const char *brname);\nint linux_br_add_if(int sock, const char *brname, const char *ifname);\nint linux_br_del_if(int sock, const char *brname, const char *ifname);\nint linux_br_get(char *brname, const char *ifname);\n\n#endif /* LINUX_IOCTL_H */\n"
  },
  {
    "path": "hostapd_wrapper/src/drivers/netlink_fake.c",
    "content": "/*\n * Netlink helper functions for driver wrappers\n * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n\n#include \"includes.h\"\n\n#include \"common.h\"\n#include \"eloop.h\"\n#include \"priv_netlink.h\"\n#include \"netlink_fake.h\"\n\n\n\nstruct netlink_data {\n\tstruct netlink_config *cfg;\n\tint sock;\n};\n\n\nstatic void netlink_receive_link(struct netlink_data *netlink,\n\t\t\t\t void (*cb)(void *ctx, struct ifinfomsg *ifi,\n\t\t\t\t\t    u8 *buf, size_t len),\n\t\t\t\t struct nlmsghdr *h)\n{\n\n\treturn;\n}\n\n\nstatic void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx)\n{\n\treturn;\n}\n\n\nstruct netlink_data * netlink_init(struct netlink_config *cfg)\n{\n\n\tstruct netlink_data *netlink;\n\tstruct sockaddr_nl local;\n\n\tnetlink = os_zalloc(sizeof(*netlink));\n\tif (netlink == NULL)\n\t\treturn NULL;\n\n\tnetlink->cfg = cfg;\n\n\tnetlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);\n\n\tos_memset(&local, 0, sizeof(local));\n\tlocal.nl_family = AF_NETLINK;\n\tlocal.nl_groups = RTMGRP_LINK;\n\n\teloop_register_read_sock(netlink->sock, netlink_receive, netlink,\n\t\t\t\t NULL);\n\n\treturn netlink;\n\n}\n\n\nvoid netlink_deinit(struct netlink_data *netlink)\n{\n\treturn;\n}\n\nint netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex,\n\t\t\t   int linkmode, int operstate){\n\n\treturn 0;\n}\n"
  },
  {
    "path": "hostapd_wrapper/src/drivers/netlink_fake.h",
    "content": "/*\n * Netlink helper functions for driver wrappers\n * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n#ifndef NETLINK_H\n#define NETLINK_H\n\nstruct netlink_data;\nstruct ifinfomsg;\n\nstruct netlink_config {\n\tvoid *ctx;\n\tvoid (*newlink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf,\n\t\t\t   size_t len);\n\tvoid (*dellink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf,\n\t\t\t   size_t len);\n};\n\nstruct netlink_data * netlink_init(struct netlink_config *cfg);\nvoid netlink_deinit(struct netlink_data *netlink);\nint netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex,\n\t\t\t   int linkmode, int operstate);\n\n#endif /* NETLINK_H */\n"
  },
  {
    "path": "ieee802_11_defs.h",
    "content": "/*\n * IEEE 802.11 Frame type definitions\n * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>\n * Copyright (c) 2007-2008 Intel Corporation\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n#ifndef IEEE802_11_DEFS_H\n#define IEEE802_11_DEFS_H\n\n/* IEEE 802.11 defines */\n\n#define WLAN_FC_PVER        0x0003\n#define WLAN_FC_TODS        0x0100\n#define WLAN_FC_FROMDS      0x0200\n#define WLAN_FC_MOREFRAG    0x0400\n#define WLAN_FC_RETRY       0x0800\n#define WLAN_FC_PWRMGT      0x1000\n#define WLAN_FC_MOREDATA    0x2000\n#define WLAN_FC_ISWEP       0x4000\n#define WLAN_FC_ORDER       0x8000\n\n#define WLAN_FC_GET_TYPE(fc)    (((fc) & 0x000c) >> 2)\n#define WLAN_FC_GET_STYPE(fc)   (((fc) & 0x00f0) >> 4)\n\n#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))\n#define WLAN_GET_SEQ_SEQ(seq) \\\n    (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)\n\n#define WLAN_FC_TYPE_MGMT       0\n#define WLAN_FC_TYPE_CTRL       1\n#define WLAN_FC_TYPE_DATA       2\n\n/* management */\n#define WLAN_FC_STYPE_ASSOC_REQ     0\n#define WLAN_FC_STYPE_ASSOC_RESP    1\n#define WLAN_FC_STYPE_REASSOC_REQ   2\n#define WLAN_FC_STYPE_REASSOC_RESP  3\n#define WLAN_FC_STYPE_PROBE_REQ     4\n#define WLAN_FC_STYPE_PROBE_RESP    5\n#define WLAN_FC_STYPE_BEACON        8\n#define WLAN_FC_STYPE_ATIM      9\n#define WLAN_FC_STYPE_DISASSOC      10\n#define WLAN_FC_STYPE_AUTH      11\n#define WLAN_FC_STYPE_DEAUTH        12\n#define WLAN_FC_STYPE_ACTION        13\n\n/* control */\n#define WLAN_FC_STYPE_PSPOLL        10\n#define WLAN_FC_STYPE_RTS       11\n#define WLAN_FC_STYPE_CTS       12\n#define WLAN_FC_STYPE_ACK       13\n#define WLAN_FC_STYPE_CFEND     14\n#define WLAN_FC_STYPE_CFENDACK      15\n\n/* data */\n#define WLAN_FC_STYPE_DATA      0\n#define WLAN_FC_STYPE_DATA_CFACK    1\n#define WLAN_FC_STYPE_DATA_CFPOLL   2\n#define WLAN_FC_STYPE_DATA_CFACKPOLL    3\n#define WLAN_FC_STYPE_NULLFUNC      4\n#define WLAN_FC_STYPE_CFACK     5\n#define WLAN_FC_STYPE_CFPOLL        6\n#define WLAN_FC_STYPE_CFACKPOLL     7\n#define WLAN_FC_STYPE_QOS_DATA      8\n#define WLAN_FC_STYPE_QOS_DATA_CFACK    9\n#define WLAN_FC_STYPE_QOS_DATA_CFPOLL   10\n#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL    11\n#define WLAN_FC_STYPE_QOS_NULL      12\n#define WLAN_FC_STYPE_QOS_CFPOLL    14\n#define WLAN_FC_STYPE_QOS_CFACKPOLL 15\n\n/* Authentication algorithms */\n#define WLAN_AUTH_OPEN          0\n#define WLAN_AUTH_SHARED_KEY        1\n#define WLAN_AUTH_FT            2\n#define WLAN_AUTH_LEAP          128\n\n#define WLAN_AUTH_CHALLENGE_LEN 128\n\n#define WLAN_CAPABILITY_ESS BIT(0)\n#define WLAN_CAPABILITY_IBSS BIT(1)\n#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)\n#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)\n#define WLAN_CAPABILITY_PRIVACY BIT(4)\n#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)\n#define WLAN_CAPABILITY_PBCC BIT(6)\n#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)\n#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)\n#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)\n#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)\n\n/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */\n#define WLAN_STATUS_SUCCESS 0\n#define WLAN_STATUS_UNSPECIFIED_FAILURE 1\n#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2\n#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3\n#define WLAN_STATUS_SECURITY_DISABLED 5\n#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6\n#define WLAN_STATUS_NOT_IN_SAME_BSS 7\n#define WLAN_STATUS_CAPS_UNSUPPORTED 10\n#define WLAN_STATUS_REASSOC_NO_ASSOC 11\n#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12\n#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13\n#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14\n#define WLAN_STATUS_CHALLENGE_FAIL 15\n#define WLAN_STATUS_AUTH_TIMEOUT 16\n#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17\n#define WLAN_STATUS_ASSOC_DENIED_RATES 18\n/* IEEE 802.11b */\n#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19\n#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20\n#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21\n/* IEEE 802.11h */\n#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22\n#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23\n#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24\n/* IEEE 802.11g */\n#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25\n#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26\n#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27\n#define WLAN_STATUS_R0KH_UNREACHABLE 28\n#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29\n/* IEEE 802.11w */\n#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30\n#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31\n#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32\n#define WLAN_STATUS_REQUEST_DECLINED 37\n#define WLAN_STATUS_INVALID_PARAMETERS 38\n/* IEEE 802.11i */\n#define WLAN_STATUS_INVALID_IE 40\n#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41\n#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42\n#define WLAN_STATUS_AKMP_NOT_VALID 43\n#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44\n#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45\n#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46\n#define WLAN_STATUS_TS_NOT_CREATED 47\n#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48\n#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49\n#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50\n#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51\n/* IEEE 802.11r */\n#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52\n#define WLAN_STATUS_INVALID_PMKID 53\n#define WLAN_STATUS_INVALID_MDIE 54\n#define WLAN_STATUS_INVALID_FTIE 55\n#define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59\n#define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60\n#define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61\n#define WLAN_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62\n#define WLAN_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63\n#define WLAN_STATUS_REQ_REFUSED_HOME 64\n#define WLAN_STATUS_ADV_SRV_UNREACHABLE 65\n#define WLAN_STATUS_REQ_REFUSED_SSPN 67\n#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68\n#define WLAN_STATUS_INVALID_RSNIE 72\n#define WLAN_STATUS_TRANSMISSION_FAILURE 79\n\n/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */\n#define WLAN_REASON_UNSPECIFIED 1\n#define WLAN_REASON_PREV_AUTH_NOT_VALID 2\n#define WLAN_REASON_DEAUTH_LEAVING 3\n#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4\n#define WLAN_REASON_DISASSOC_AP_BUSY 5\n#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6\n#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7\n#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8\n#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9\n/* IEEE 802.11h */\n#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10\n#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11\n/* IEEE 802.11i */\n#define WLAN_REASON_INVALID_IE 13\n#define WLAN_REASON_MICHAEL_MIC_FAILURE 14\n#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15\n#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16\n#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17\n#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18\n#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19\n#define WLAN_REASON_AKMP_NOT_VALID 20\n#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21\n#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22\n#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23\n#define WLAN_REASON_CIPHER_SUITE_REJECTED 24\n#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25\n#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26\n/* IEEE 802.11e */\n#define WLAN_REASON_DISASSOC_LOW_ACK 34\n\n/* Information Element IDs */\n#define WLAN_EID_SSID 0\n#define WLAN_EID_SUPP_RATES 1\n#define WLAN_EID_FH_PARAMS 2\n#define WLAN_EID_DS_PARAMS 3\n#define WLAN_EID_CF_PARAMS 4\n#define WLAN_EID_TIM 5\n#define WLAN_EID_IBSS_PARAMS 6\n#define WLAN_EID_COUNTRY 7\n#define WLAN_EID_CHALLENGE 16\n/* EIDs defined by IEEE 802.11h - START */\n#define WLAN_EID_PWR_CONSTRAINT 32\n#define WLAN_EID_PWR_CAPABILITY 33\n#define WLAN_EID_TPC_REQUEST 34\n#define WLAN_EID_TPC_REPORT 35\n#define WLAN_EID_SUPPORTED_CHANNELS 36\n#define WLAN_EID_CHANNEL_SWITCH 37\n#define WLAN_EID_MEASURE_REQUEST 38\n#define WLAN_EID_MEASURE_REPORT 39\n#define WLAN_EID_QUITE 40\n#define WLAN_EID_IBSS_DFS 41\n/* EIDs defined by IEEE 802.11h - END */\n#define WLAN_EID_ERP_INFO 42\n#define WLAN_EID_HT_CAP 45\n#define WLAN_EID_RSN 48\n#define WLAN_EID_EXT_SUPP_RATES 50\n#define WLAN_EID_MOBILITY_DOMAIN 54\n#define WLAN_EID_FAST_BSS_TRANSITION 55\n#define WLAN_EID_TIMEOUT_INTERVAL 56\n#define WLAN_EID_RIC_DATA 57\n#define WLAN_EID_HT_OPERATION 61\n#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62\n#define WLAN_EID_TIME_ADVERTISEMENT 69\n#define WLAN_EID_20_40_BSS_COEXISTENCE 72\n#define WLAN_EID_20_40_BSS_INTOLERANT 73\n#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74\n#define WLAN_EID_MMIE 76\n#define WLAN_EID_TIME_ZONE 98\n#define WLAN_EID_LINK_ID 101\n#define WLAN_EID_INTERWORKING 107\n#define WLAN_EID_ADV_PROTO 108\n#define WLAN_EID_ROAMING_CONSORTIUM 111\n#define WLAN_EID_EXT_CAPAB 127\n#define WLAN_EID_VENDOR_SPECIFIC 221\n\n/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */\n#define WLAN_ACTION_SPECTRUM_MGMT 0\n#define WLAN_ACTION_QOS 1\n#define WLAN_ACTION_DLS 2\n#define WLAN_ACTION_BLOCK_ACK 3\n#define WLAN_ACTION_PUBLIC 4\n#define WLAN_ACTION_RADIO_MEASUREMENT 5\n#define WLAN_ACTION_FT 6\n#define WLAN_ACTION_HT 7\n#define WLAN_ACTION_SA_QUERY 8\n#define WLAN_ACTION_WNM 10\n#define WLAN_ACTION_UNPROTECTED_WNM 11\n#define WLAN_ACTION_TDLS 12\n#define WLAN_ACTION_WMM 17\t/* WMM Specification 1.1 */\n#define WLAN_ACTION_VENDOR_SPECIFIC 127\n\n/* Public action codes */\n#define WLAN_PA_VENDOR_SPECIFIC 9\n#define WLAN_PA_GAS_INITIAL_REQ 10\n#define WLAN_PA_GAS_INITIAL_RESP 11\n#define WLAN_PA_GAS_COMEBACK_REQ 12\n#define WLAN_PA_GAS_COMEBACK_RESP 13\n#define WLAN_TDLS_DISCOVERY_RESPONSE 14\n\n/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */\n#define WLAN_SA_QUERY_REQUEST 0\n#define WLAN_SA_QUERY_RESPONSE 1\n\n#define WLAN_SA_QUERY_TR_ID_LEN 2\n\n/* TDLS action codes */\n#define WLAN_TDLS_SETUP_REQUEST 0\n#define WLAN_TDLS_SETUP_RESPONSE 1\n#define WLAN_TDLS_SETUP_CONFIRM 2\n#define WLAN_TDLS_TEARDOWN 3\n#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4\n#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5\n#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6\n#define WLAN_TDLS_PEER_PSM_REQUEST 7\n#define WLAN_TDLS_PEER_PSM_RESPONSE 8\n#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9\n#define WLAN_TDLS_DISCOVERY_REQUEST 10\n\n/* Timeout Interval Type */\n#define WLAN_TIMEOUT_REASSOC_DEADLINE 1\n#define WLAN_TIMEOUT_KEY_LIFETIME 2\n#define WLAN_TIMEOUT_ASSOC_COMEBACK 3\n\n/* Interworking element (IEEE 802.11u) - Access Network Options */\n#define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f\n#define INTERWORKING_ANO_INTERNET 0x10\n#define INTERWORKING_ANO_ASRA 0x20\n#define INTERWORKING_ANO_ESR 0x40\n#define INTERWORKING_ANO_UESA 0x80\n\n#define INTERWORKING_ANT_PRIVATE 0\n#define INTERWORKING_ANT_PRIVATE_WITH_GUEST 1\n#define INTERWORKING_ANT_CHARGEABLE_PUBLIC 2\n#define INTERWORKING_ANT_FREE_PUBLIC 3\n#define INTERWORKING_ANT_PERSONAL_DEVICE 4\n#define INTERWORKING_ANT_EMERGENCY_SERVICES 5\n#define INTERWORKING_ANT_TEST 6\n#define INTERWORKING_ANT_WILDCARD 15\n\n/* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */\nenum adv_proto_id {\n\tACCESS_NETWORK_QUERY_PROTOCOL = 0,\n\tMIH_INFO_SERVICE = 1,\n\tMIH_CMD_AND_EVENT_DISCOVERY = 2,\n\tEMERGENCY_ALERT_SYSTEM = 3,\n\tADV_PROTO_VENDOR_SPECIFIC = 221\n};\n\n/* Access Network Query Protocol info ID definitions (IEEE Std 802.11u-2011) */\nenum anqp_info_id {\n\tANQP_QUERY_LIST = 256,\n\tANQP_CAPABILITY_LIST = 257,\n\tANQP_VENUE_NAME = 258,\n\tANQP_EMERGENCY_CALL_NUMBER = 259,\n\tANQP_NETWORK_AUTH_TYPE = 260,\n\tANQP_ROAMING_CONSORTIUM = 261,\n\tANQP_IP_ADDR_TYPE_AVAILABILITY = 262,\n\tANQP_NAI_REALM = 263,\n\tANQP_3GPP_CELLULAR_NETWORK = 264,\n\tANQP_AP_GEOSPATIAL_LOCATION = 265,\n\tANQP_AP_CIVIC_LOCATION = 266,\n\tANQP_AP_LOCATION_PUBLIC_URI = 267,\n\tANQP_DOMAIN_NAME = 268,\n\tANQP_EMERGENCY_ALERT_URI = 269,\n\tANQP_EMERGENCY_NAI = 271,\n\tANQP_VENDOR_SPECIFIC = 56797\n};\n\n/* NAI Realm list - EAP Method subfield - Authentication Parameter ID */\nenum nai_realm_eap_auth_param {\n\tNAI_REALM_EAP_AUTH_EXPANDED_EAP_METHOD = 1,\n\tNAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH = 2,\n\tNAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD = 3,\n\tNAI_REALM_EAP_AUTH_EXPANDED_INNER_EAP_METHOD = 4,\n\tNAI_REALM_EAP_AUTH_CRED_TYPE = 5,\n\tNAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE = 6,\n\tNAI_REALM_EAP_AUTH_VENDOR_SPECIFIC = 221\n};\n\nenum nai_realm_eap_auth_inner_non_eap {\n\tNAI_REALM_INNER_NON_EAP_PAP = 1,\n\tNAI_REALM_INNER_NON_EAP_CHAP = 2,\n\tNAI_REALM_INNER_NON_EAP_MSCHAP = 3,\n\tNAI_REALM_INNER_NON_EAP_MSCHAPV2 = 4\n};\n\nenum nai_realm_eap_cred_type {\n\tNAI_REALM_CRED_TYPE_SIM = 1,\n\tNAI_REALM_CRED_TYPE_USIM = 2,\n\tNAI_REALM_CRED_TYPE_NFC_SECURE_ELEMENT = 3,\n\tNAI_REALM_CRED_TYPE_HARDWARE_TOKEN = 4,\n\tNAI_REALM_CRED_TYPE_SOFTOKEN = 5,\n\tNAI_REALM_CRED_TYPE_CERTIFICATE = 6,\n\tNAI_REALM_CRED_TYPE_USERNAME_PASSWORD = 7,\n\tNAI_REALM_CRED_TYPE_NONE = 8,\n\tNAI_REALM_CRED_TYPE_ANONYMOUS = 9,\n\tNAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10\n};\n\n#ifdef _MSC_VER\n#pragma pack(push, 1)\n#endif\t\t\t\t/* _MSC_VER */\n\nstruct ieee80211_hdr {\n\tle16 frame_control;\n\tle16 duration_id;\n\tu8 addr1[6];\n\tu8 addr2[6];\n\tu8 addr3[6];\n\tle16 seq_ctrl;\n\t/* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame\n\t */\n} STRUCT_PACKED;\n\n#define IEEE80211_DA_FROMDS addr1\n#define IEEE80211_BSSID_FROMDS addr2\n#define IEEE80211_SA_FROMDS addr3\n\n#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))\n\n#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))\n\nstruct ieee80211_mgmt {\n\tle16 frame_control;\n\tle16 duration;\n\tu8 da[6];\n\tu8 sa[6];\n\tu8 bssid[6];\n\tle16 seq_ctrl;\n\tunion {\n\t\tstruct {\n\t\t\tle16 auth_alg;\n\t\t\tle16 auth_transaction;\n\t\t\tle16 status_code;\n\t\t\t/* possibly followed by Challenge text */\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED auth;\n\t\tstruct {\n\t\t\tle16 reason_code;\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED deauth;\n\t\tstruct {\n\t\t\tle16 capab_info;\n\t\t\tle16 listen_interval;\n\t\t\t/* followed by SSID and Supported rates */\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED assoc_req;\n\t\tstruct {\n\t\t\tle16 capab_info;\n\t\t\tle16 status_code;\n\t\t\tle16 aid;\n\t\t\t/* followed by Supported rates */\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED assoc_resp, reassoc_resp;\n\t\tstruct {\n\t\t\tle16 capab_info;\n\t\t\tle16 listen_interval;\n\t\t\tu8 current_ap[6];\n\t\t\t/* followed by SSID and Supported rates */\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED reassoc_req;\n\t\tstruct {\n\t\t\tle16 reason_code;\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED disassoc;\n\t\tstruct {\n\t\t\tu8 timestamp[8];\n\t\t\tle16 beacon_int;\n\t\t\tle16 capab_info;\n\t\t\t/* followed by some of SSID, Supported rates,\n\t\t\t * FH Params, DS Params, CF Params, IBSS Params, TIM */\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED beacon;\n\t\tstruct {\n\t\t\t/* only variable items: SSID, Supported rates */\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED probe_req;\n\t\tstruct {\n\t\t\tu8 timestamp[8];\n\t\t\tle16 beacon_int;\n\t\t\tle16 capab_info;\n\t\t\t/* followed by some of SSID, Supported rates,\n\t\t\t * FH Params, DS Params, CF Params, IBSS Params */\n\t\t\tu8 variable[0];\n\t\t} STRUCT_PACKED probe_resp;\n\t\tstruct {\n\t\t\tu8 category;\n\t\t\tunion {\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action_code;\n\t\t\t\t\tu8 dialog_token;\n\t\t\t\t\tu8 status_code;\n\t\t\t\t\tu8 variable[0];\n\t\t\t\t} STRUCT_PACKED wmm_action;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action_code;\n\t\t\t\t\tu8 element_id;\n\t\t\t\t\tu8 length;\n\t\t\t\t\tu8 switch_mode;\n\t\t\t\t\tu8 new_chan;\n\t\t\t\t\tu8 switch_count;\n\t\t\t\t} STRUCT_PACKED chan_switch;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action;\n\t\t\t\t\tu8 sta_addr[ETH_ALEN];\n\t\t\t\t\tu8 target_ap_addr[ETH_ALEN];\n\t\t\t\t\tu8 variable[0];\t/* FT Request */\n\t\t\t\t} STRUCT_PACKED ft_action_req;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action;\n\t\t\t\t\tu8 sta_addr[ETH_ALEN];\n\t\t\t\t\tu8 target_ap_addr[ETH_ALEN];\n\t\t\t\t\tle16 status_code;\n\t\t\t\t\tu8 variable[0];\t/* FT Request */\n\t\t\t\t} STRUCT_PACKED ft_action_resp;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action;\n\t\t\t\t\tu8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];\n\t\t\t\t} STRUCT_PACKED sa_query_req;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action;\t/* */\n\t\t\t\t\tu8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];\n\t\t\t\t} STRUCT_PACKED sa_query_resp;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action;\n\t\t\t\t\tu8 variable[0];\n\t\t\t\t} STRUCT_PACKED public_action;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action;\t/* 9 */\n\t\t\t\t\tu8 oui[3];\n\t\t\t\t\t/* Vendor-specific content */\n\t\t\t\t\tu8 variable[0];\n\t\t\t\t} STRUCT_PACKED vs_public_action;\n\t\t\t\tstruct {\n\t\t\t\t\tu8 action;\t/* 7 */\n\t\t\t\t\tu8 dialog_token;\n\t\t\t\t\tu8 req_mode;\n\t\t\t\t\tle16 disassoc_timer;\n\t\t\t\t\tu8 validity_interval;\n\t\t\t\t\t/* BSS Termination Duration (optional),\n\t\t\t\t\t * Session Information URL (optional),\n\t\t\t\t\t * BSS Transition Candidate List\n\t\t\t\t\t * Entries */\n\t\t\t\t\tu8 variable[0];\n\t\t\t\t} STRUCT_PACKED bss_tm_req;\n\t\t\t} u;\n\t\t} STRUCT_PACKED action;\n\t} u;\n} STRUCT_PACKED;\n\nstruct ieee80211_ht_capabilities {\n\tle16 ht_capabilities_info;\n\tu8 a_mpdu_params;\n\tu8 supported_mcs_set[16];\n\tle16 ht_extended_capabilities;\n\tle32 tx_bf_capability_info;\n\tu8 asel_capabilities;\n} STRUCT_PACKED;\n\nstruct ieee80211_ht_operation {\n\tu8 control_chan;\n\tu8 ht_param;\n\tle16 operation_mode;\n\tle16 stbc_param;\n\tu8 basic_set[16];\n} STRUCT_PACKED;\n\n#ifdef _MSC_VER\n#pragma pack(pop)\n#endif\t\t\t\t/* _MSC_VER */\n\n#define ERP_INFO_NON_ERP_PRESENT BIT(0)\n#define ERP_INFO_USE_PROTECTION BIT(1)\n#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)\n\n#define HT_CAP_INFO_LDPC_CODING_CAP     ((u16) BIT(0))\n#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET  ((u16) BIT(1))\n#define HT_CAP_INFO_SMPS_MASK           ((u16) (BIT(2) | BIT(3)))\n#define HT_CAP_INFO_SMPS_STATIC         ((u16) 0)\n#define HT_CAP_INFO_SMPS_DYNAMIC        ((u16) BIT(2))\n#define HT_CAP_INFO_SMPS_DISABLED       ((u16) (BIT(2) | BIT(3)))\n#define HT_CAP_INFO_GREEN_FIELD         ((u16) BIT(4))\n#define HT_CAP_INFO_SHORT_GI20MHZ       ((u16) BIT(5))\n#define HT_CAP_INFO_SHORT_GI40MHZ       ((u16) BIT(6))\n#define HT_CAP_INFO_TX_STBC         ((u16) BIT(7))\n#define HT_CAP_INFO_RX_STBC_MASK        ((u16) (BIT(8) | BIT(9)))\n#define HT_CAP_INFO_RX_STBC_1           ((u16) BIT(8))\n#define HT_CAP_INFO_RX_STBC_12          ((u16) BIT(9))\n#define HT_CAP_INFO_RX_STBC_123         ((u16) (BIT(8) | BIT(9)))\n#define HT_CAP_INFO_DELAYED_BA          ((u16) BIT(10))\n#define HT_CAP_INFO_MAX_AMSDU_SIZE      ((u16) BIT(11))\n#define HT_CAP_INFO_DSSS_CCK40MHZ       ((u16) BIT(12))\n#define HT_CAP_INFO_PSMP_SUPP           ((u16) BIT(13))\n#define HT_CAP_INFO_40MHZ_INTOLERANT        ((u16) BIT(14))\n#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT   ((u16) BIT(15))\n\n#define EXT_HT_CAP_INFO_PCO         ((u16) BIT(0))\n#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET   1\n#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8\n#define EXT_HT_CAP_INFO_HTC_SUPPORTED       ((u16) BIT(10))\n#define EXT_HT_CAP_INFO_RD_RESPONDER        ((u16) BIT(11))\n\n#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0))\n#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1))\n#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2))\n#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3))\n#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4))\n#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5))\n#define TX_BEAMFORM_CAP_CALIB_OFFSET 6\n#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8))\n#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9))\n#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10))\n#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11\n#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13\n#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15\n#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17\n#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19\n#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21\n#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23\n#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25\n\n#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0))\n#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1))\n#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2))\n#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3))\n#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4))\n#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5))\n#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6))\n\n#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK    ((u8) BIT(0) | BIT(1))\n#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE       ((u8) BIT(0))\n#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW       ((u8) BIT(0) | BIT(1))\n#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH       ((u8) BIT(2))\n#define HT_INFO_HT_PARAM_RIFS_MODE          ((u8) BIT(3))\n#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY       ((u8) BIT(4))\n#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY   ((u8) BIT(5))\n\n#define OP_MODE_PURE                    0\n#define OP_MODE_MAY_BE_LEGACY_STAS      1\n#define OP_MODE_20MHZ_HT_STA_ASSOCED    2\n#define OP_MODE_MIXED                   3\n\n#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \\\n        ((le16) (0x0001 | 0x0002))\n#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET       0\n#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT  ((u8) BIT(2))\n#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))\n#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT   ((u8) BIT(4))\n\n#define HT_INFO_STBC_PARAM_DUAL_BEACON          ((u16) BIT(6))\n#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT        ((u16) BIT(7))\n#define HT_INFO_STBC_PARAM_SECONDARY_BCN        ((u16) BIT(8))\n#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED    ((u16) BIT(9))\n#define HT_INFO_STBC_PARAM_PCO_ACTIVE           ((u16) BIT(10))\n#define HT_INFO_STBC_PARAM_PCO_PHASE            ((u16) BIT(11))\n\n#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127\n\n#define OUI_MICROSOFT 0x0050f2\t/* Microsoft (also used in Wi-Fi specs)\n\t\t\t\t * 00:50:F2 */\n#define WPA_IE_VENDOR_TYPE 0x0050f201\n#define WPS_IE_VENDOR_TYPE 0x0050f204\n#define OUI_WFA 0x506f9a\n#define P2P_IE_VENDOR_TYPE 0x506f9a09\n\n#define WMM_OUI_TYPE 2\n#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0\n#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1\n#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2\n#define WMM_VERSION 1\n\n#define WMM_ACTION_CODE_ADDTS_REQ 0\n#define WMM_ACTION_CODE_ADDTS_RESP 1\n#define WMM_ACTION_CODE_DELTS 2\n\n#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0\n#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1\n/* 2 - Reserved */\n#define WMM_ADDTS_STATUS_REFUSED 3\n/* 4-255 - Reserved */\n\n/* WMM TSPEC Direction Field Values */\n#define WMM_TSPEC_DIRECTION_UPLINK 0\n#define WMM_TSPEC_DIRECTION_DOWNLINK 1\n/* 2 - Reserved */\n#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3\n\n/*\n * WMM Information Element (used in (Re)Association Request frames; may also be\n * used in Beacon frames)\n */\nstruct wmm_information_element {\n\t/* Element ID: 221 (0xdd); Length: 7 */\n\t/* required fields for WMM version 1 */\n\tu8 oui[3];\t\t/* 00:50:f2 */\n\tu8 oui_type;\t\t/* 2 */\n\tu8 oui_subtype;\t\t/* 0 */\n\tu8 version;\t\t/* 1 for WMM version 1.0 */\n\tu8 qos_info;\t\t/* AP/STA specific QoS info */\n\n} STRUCT_PACKED;\n\n#define WMM_AC_AIFSN_MASK 0x0f\n#define WMM_AC_AIFNS_SHIFT 0\n#define WMM_AC_ACM 0x10\n#define WMM_AC_ACI_MASK 0x60\n#define WMM_AC_ACI_SHIFT 5\n\n#define WMM_AC_ECWMIN_MASK 0x0f\n#define WMM_AC_ECWMIN_SHIFT 0\n#define WMM_AC_ECWMAX_MASK 0xf0\n#define WMM_AC_ECWMAX_SHIFT 4\n\nstruct wmm_ac_parameter {\n\tu8 aci_aifsn;\t\t/* AIFSN, ACM, ACI */\n\tu8 cw;\t\t\t/* ECWmin, ECWmax (CW = 2^ECW - 1) */\n\tle16 txop_limit;\n} STRUCT_PACKED;\n\n/*\n * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association\n * Response frmaes)\n */\nstruct wmm_parameter_element {\n\t/* Element ID: 221 (0xdd); Length: 24 */\n\t/* required fields for WMM version 1 */\n\tu8 oui[3];\t\t/* 00:50:f2 */\n\tu8 oui_type;\t\t/* 2 */\n\tu8 oui_subtype;\t\t/* 1 */\n\tu8 version;\t\t/* 1 for WMM version 1.0 */\n\tu8 qos_info;\t\t/* AP/STA specific QoS info */\n\tu8 reserved;\t\t/* 0 */\n\tstruct wmm_ac_parameter ac[4];\t/* AC_BE, AC_BK, AC_VI, AC_VO */\n\n} STRUCT_PACKED;\n\n/* WMM TSPEC Element */\nstruct wmm_tspec_element {\n\tu8 eid;\t\t\t/* 221 = 0xdd */\n\tu8 length;\t\t/* 6 + 55 = 61 */\n\tu8 oui[3];\t\t/* 00:50:f2 */\n\tu8 oui_type;\t\t/* 2 */\n\tu8 oui_subtype;\t\t/* 2 */\n\tu8 version;\t\t/* 1 */\n\t/* WMM TSPEC body (55 octets): */\n\tu8 ts_info[3];\n\tle16 nominal_msdu_size;\n\tle16 maximum_msdu_size;\n\tle32 minimum_service_interval;\n\tle32 maximum_service_interval;\n\tle32 inactivity_interval;\n\tle32 suspension_interval;\n\tle32 service_start_time;\n\tle32 minimum_data_rate;\n\tle32 mean_data_rate;\n\tle32 peak_data_rate;\n\tle32 maximum_burst_size;\n\tle32 delay_bound;\n\tle32 minimum_phy_rate;\n\tle16 surplus_bandwidth_allowance;\n\tle16 medium_time;\n} STRUCT_PACKED;\n\n/* Access Categories / ACI to AC coding */\nenum {\n\tWMM_AC_BE = 0 /* Best Effort */ ,\n\tWMM_AC_BK = 1 /* Background */ ,\n\tWMM_AC_VI = 2 /* Video */ ,\n\tWMM_AC_VO = 3\t\t/* Voice */\n};\n\n/* Wi-Fi Direct (P2P) */\n\n#define P2P_OUI_TYPE 9\n\nenum p2p_attr_id {\n\tP2P_ATTR_STATUS = 0,\n\tP2P_ATTR_MINOR_REASON_CODE = 1,\n\tP2P_ATTR_CAPABILITY = 2,\n\tP2P_ATTR_DEVICE_ID = 3,\n\tP2P_ATTR_GROUP_OWNER_INTENT = 4,\n\tP2P_ATTR_CONFIGURATION_TIMEOUT = 5,\n\tP2P_ATTR_LISTEN_CHANNEL = 6,\n\tP2P_ATTR_GROUP_BSSID = 7,\n\tP2P_ATTR_EXT_LISTEN_TIMING = 8,\n\tP2P_ATTR_INTENDED_INTERFACE_ADDR = 9,\n\tP2P_ATTR_MANAGEABILITY = 10,\n\tP2P_ATTR_CHANNEL_LIST = 11,\n\tP2P_ATTR_NOTICE_OF_ABSENCE = 12,\n\tP2P_ATTR_DEVICE_INFO = 13,\n\tP2P_ATTR_GROUP_INFO = 14,\n\tP2P_ATTR_GROUP_ID = 15,\n\tP2P_ATTR_INTERFACE = 16,\n\tP2P_ATTR_OPERATING_CHANNEL = 17,\n\tP2P_ATTR_INVITATION_FLAGS = 18,\n\tP2P_ATTR_VENDOR_SPECIFIC = 221\n};\n\n#define P2P_MAX_GO_INTENT 15\n\n/* P2P Capability - Device Capability bitmap */\n#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0)\n#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1)\n#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2)\n#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)\n#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)\n#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)\n\n/* P2P Capability - Group Capability bitmap */\n#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)\n#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1)\n#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2)\n#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3)\n#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4)\n#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5)\n#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)\n\n/* Invitation Flags */\n#define P2P_INVITATION_FLAGS_TYPE BIT(0)\n\n/* P2P Manageability */\n#define P2P_MAN_DEVICE_MANAGEMENT BIT(0)\n#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1)\n#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2)\n\nenum p2p_status_code {\n\tP2P_SC_SUCCESS = 0,\n\tP2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,\n\tP2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2,\n\tP2P_SC_FAIL_LIMIT_REACHED = 3,\n\tP2P_SC_FAIL_INVALID_PARAMS = 4,\n\tP2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5,\n\tP2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6,\n\tP2P_SC_FAIL_NO_COMMON_CHANNELS = 7,\n\tP2P_SC_FAIL_UNKNOWN_GROUP = 8,\n\tP2P_SC_FAIL_BOTH_GO_INTENT_15 = 9,\n\tP2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,\n\tP2P_SC_FAIL_REJECTED_BY_USER = 11,\n};\n\n#define P2P_WILDCARD_SSID \"DIRECT-\"\n#define P2P_WILDCARD_SSID_LEN 7\n\n/* P2P action frames */\nenum p2p_act_frame_type {\n\tP2P_NOA = 0,\n\tP2P_PRESENCE_REQ = 1,\n\tP2P_PRESENCE_RESP = 2,\n\tP2P_GO_DISC_REQ = 3\n};\n\n/* P2P public action frames */\nenum p2p_action_frame_type {\n\tP2P_GO_NEG_REQ = 0,\n\tP2P_GO_NEG_RESP = 1,\n\tP2P_GO_NEG_CONF = 2,\n\tP2P_INVITATION_REQ = 3,\n\tP2P_INVITATION_RESP = 4,\n\tP2P_DEV_DISC_REQ = 5,\n\tP2P_DEV_DISC_RESP = 6,\n\tP2P_PROV_DISC_REQ = 7,\n\tP2P_PROV_DISC_RESP = 8\n};\n\nenum p2p_service_protocol_type {\n\tP2P_SERV_ALL_SERVICES = 0,\n\tP2P_SERV_BONJOUR = 1,\n\tP2P_SERV_UPNP = 2,\n\tP2P_SERV_WS_DISCOVERY = 3,\n\tP2P_SERV_VENDOR_SPECIFIC = 255\n};\n\nenum p2p_sd_status {\n\tP2P_SD_SUCCESS = 0,\n\tP2P_SD_PROTO_NOT_AVAILABLE = 1,\n\tP2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2,\n\tP2P_SD_BAD_REQUEST = 3\n};\n\n#define OUI_BROADCOM 0x00904c\t/* Broadcom (Epigram) */\n\n#define VENDOR_HT_CAPAB_OUI_TYPE 0x33\t/* 00-90-4c:0x33 */\n\n/* cipher suite selectors */\n#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00\n#define WLAN_CIPHER_SUITE_WEP40     0x000FAC01\n#define WLAN_CIPHER_SUITE_TKIP      0x000FAC02\n/* reserved:                0x000FAC03 */\n#define WLAN_CIPHER_SUITE_CCMP      0x000FAC04\n#define WLAN_CIPHER_SUITE_WEP104    0x000FAC05\n#define WLAN_CIPHER_SUITE_AES_CMAC  0x000FAC06\n\n/* AKM suite selectors */\n#define WLAN_AKM_SUITE_8021X        0x000FAC01\n#define WLAN_AKM_SUITE_PSK      0x000FAC02\n\n/* IEEE 802.11v - WNM Action field values */\nenum wnm_action {\n\tWNM_EVENT_REQ = 0,\n\tWNM_EVENT_REPORT = 1,\n\tWNM_DIAGNOSTIC_REQ = 2,\n\tWNM_DIAGNOSTIC_REPORT = 3,\n\tWNM_LOCATION_CFG_REQ = 4,\n\tWNM_LOCATION_CFG_RESP = 5,\n\tWNM_BSS_TRANS_MGMT_QUERY = 6,\n\tWNM_BSS_TRANS_MGMT_REQ = 7,\n\tWNM_BSS_TRANS_MGMT_RESP = 8,\n\tWNM_FMS_REQ = 9,\n\tWNM_FMS_RESP = 10,\n\tWNM_COLLOCATED_INTERFERENCE_REQ = 11,\n\tWNM_COLLOCATED_INTERFERENCE_REPORT = 12,\n\tWNM_TFS_REQ = 13,\n\tWNM_TFS_RESP = 14,\n\tWNM_TFS_NOTIFY = 15,\n\tWNM_SLEEP_MODE_REQ = 16,\n\tWNM_SLEEP_MODE_RESP = 17,\n\tWNM_TIM_BROADCAST_REQ = 18,\n\tWNM_TIM_BROADCAST_RESP = 19,\n\tWNM_QOS_TRAFFIC_CAPAB_UPDATE = 20,\n\tWNM_CHANNEL_USAGE_REQ = 21,\n\tWNM_CHANNEL_USAGE_RESP = 22,\n\tWNM_DMS_REQ = 23,\n\tWNM_DMS_RESP = 24,\n\tWNM_TIMING_MEASUREMENT_REQ = 25,\n\tWNM_NOTIFICATION_REQ = 26,\n\tWNM_NOTIFICATION_RESP = 27\n};\n\n/* IEEE 802.11v - BSS Transition Management Request - Request Mode */\n#define WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED BIT(0)\n#define WNM_BSS_TM_REQ_ABRIDGED BIT(1)\n#define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2)\n#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)\n#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)\n\n#endif\t\t\t\t/* IEEE802_11_DEFS_H */\n"
  },
  {
    "path": "modifiche_daniele.txt",
    "content": "ACBinding.c         : n/c\nACBinding.h         : n/c\nAC.c                : n/c\nACConfigFile.c      : n/c\nACConfigureState.c  : n/c\nACDataCheckState.c  : n/c\nACDiscoveryState.c  : n/c\nACInterface.c       line 106: è stata aggiunta la funzione CWActionMenu() per inserire un nuovo menù di scelte.  \n            line 243: è stata inserita la funzione CWSetInterfaceCmd() per settare la variabile gWTPs[selection].interfaceCommand al \n                  valore passato come parametro.\n            line 404: è stata modificata la funzione CWInterface(), all'interno dello switch sono stati aggiunti due nuovi casi e e                  modificati alcuni di quelli già esistenti. \n\nACInterface.h       line 35: è stata aggiunta la variabile globale  CLEAR_CONFIG_MSG_CMD   \nACJoinState.c       : n/c\nACMainLoop.c        line 614: è stato inserito il case CLEAR_CONFIG_MSG_CMD per prevedere l'assemblaggio del messaggio ClearConfiguration.     \nACMultiHomedSocket.c    : n/c\nACMultiHomedSocket.h    : n/c\nACProtocol.c        line 145: è stata aggiunta la funzione CWAssembleMsgElemAddStation() per l'assemblaggio dei messages elements per                            il msg AddStation.\n            line 517: è stata inserita la funzione CWParseMsgElemDataTransferData() per il parsing dei messages elements contenuti nel msg \n                  DataTransfer.\n\nACProtocol.h        line 134: è stato aggiunto il prototipo della funzione CWAssembleMsgElemAddStation();\n            line 146: è stato aggiunto il prototipo della funzione CWParseMsgElemDataTransferData();\n\nACProtocol_User.c   : n/c\nACRetransmission.c  : n/c\nACRunState.c        line 46: é stato aggiunto il prototipo della funzione CWParseClearConfigurationResponseMessage();\n            line 50: è stato aggiunto il prototipo della funzione CWParseStationConfigurationResponseMessage();\n            line 54: è stato aggiunto il prototipo della funzione CWParseWTPDataTransferRequestMessage();\n            line 58: è stato aggiunto il prototipo della funzione CWAssembleWTPDataTransferResponse();\n            line 97: è stata inserita la variabile StationMacAddr[MAC_ADDR_LEN] per mantenere l'indirizzo mac della stazione associata.\n            line 101: è stato inserito un blocco di codice (fino a line 125) per le azioni da compiere nel caso l'AC riceva un pacchetto                     dati.\n            line 202: è stato aggiunto il case CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE all'interno dello switch (line 136) per                      gestire la ricezione di un msg di StationConfigurationResponse.\n            line 213: è stato inserito il case CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_RESPONSE per gestire la ricezione di un msg di                  ClearConfigurationResponse.\n            line 235: è stato aggiunto il case CW_MSG_TYPE_VALUE_DATA_TRANSFER_REQUEST per la gestione di un messaggio DataTransferRequest                       da parte del WTP.\n            line 388: è stata aggiunta l'implementazione della funzione  CWParseClearConfigurationResponseMessage() per il parsing del                       ClearConfigurationResponseMessage.\n            line 423: è stata aggiunta l'implementazione della funzione  CWParseStationConfigurationResponseMessage() per il parsing del                     StationConfigurationResponseMessage.\n            line 470: è stata aggiunta l'implementazione della funzione CWParseWTPDataTransferRequestMessage() per il parsing del                    WTPDataTransferRequest.\n            line 735: è stata aggiunta l'implementazione della funzione CWAssembleWTPDataTransferResponse() per l'assemblaggio del                       WTPDataTransferResponse.\n            line 1030: è stata aggiunta l'implementazione della funzione CWAssembleClearConfigurationRequest() per l'assemblaggio di un                       ClearConfigurationRequest.\n            line 1051: è stata aggiunta l'implementazione della funzione CWAssembleStationConfigurationRequest() per l'assemblaggio di un                     StationConfigurationRequest.\n\nACSettingsFile.c    : n/c\nconfig.h        : n/c\nCWAC.h          line 46: è stata aggiunta la variabile MAC_ADDR_LEN\n            line 47: è stata aggiunta la variabile DEST_ADDR_START \n            line 48: è stata aggiunta la variabile SOURCE_ADDR_START   \n            line 160: è stato inserito il prototipo della funzione CWAssembleStationConfigurationRequest();\n            line 165: è stato inserito il prototipo della funzione CWAssembleClearConfigurationRequest();\n\nCWBinding.c     : n/c\nCWBinding.h     : n/c\nCWCommon.c      : n/c\nCWCommon.h      : n/c\nCWConfigFile.c      : n/c\nCWConfigFile.h      : n/c\nCWErrorHandling.c   : n/c\nCWErrorHandling.h   : n/c\nCWList.c        : n/c\nCWList.h        : n/c\nCWLog.c         : n/c\nCWLog.h         : n/c\nCWNetwork.c     : n/c\nCWNetwork.h     : n/c\nCWOpenSSLBio.c      : n/c\nCWProtocol.c        : n/c\nCWProtocol.h        line 258: è stato inserito un nuovo valore per la variabile CW_NEIGHBORDEAD_INTERVAL_DEFAULT (tale modifica si rende necessaria                  a causa di un problema riscontrato con la gestione dei timer a runtime da parte del WTP sull'AP).\n            line 264: è stato inserito un nuovo valore per la variabile CW_ECHO_INTERVAL_DEFAULT (come sopra...). \nCWRandom.c      : n/c\nCWRandom.h      : n/c\nCWSafeList.c        : n/c\nCWSafeList.h        : n/c\nCWSecurity.c        : n/c\nCWSecurity.h        : n/c\nCWStevens.c     : n/c\nCWStevens.h     : n/c\nCWThread.c      : n/c\nCWThread.h      : n/c\nCWTimer.h       : n/c\nCWWTP.h         line 104: è stato aggiunto il prototipo della funzione CWAssembleWTPDataTansferRequest() implementata in WTPRunState.c\n            line 147: è stata inserita la direttiva del preprocessore BCM per distinguere la compilazione normale dalla cross-compilazione\n            line 159: è stata inserito il prototipo della funzione set_wme_cwmin() implementata in WTPBcmDriverInteraction.c\n            line 160: è stata inserito il prototipo della funzione set_wme_cwmax() implementata in WTPBcmDriverInteraction.c\n            line 170: è stata inserito il prototipo della funzione set_wme_aifsn() implementata in WTPBcmDriverInteraction.c\ntimerlib.c      : n/c\ntimerlib.h      : n/c\nwireless_copy.h     : n/c\nWTPBcmDriverInteraction.c/.h : nuovo file introdotto per la gestione delle ioctl per l'accesso ai driver Broadcom.\nWTPBcmFrameReceive.c/.h      : nuovo file introdotto per la gestione delle ioctl per l'accesso ai driver Broadcom.(ricezione frame dalle stazioni).\n\nWTPBinding.c        line 90:  è stata inserita la direttiva del preprocessore BCM per distinguere la compilazione normale dalla cross-compilazione\n            line 91: è stata inserito un duplicato della CWWTPInitBinding() per la cross comiplazione per inizializzare i valori del QoS\n                sui driver Broadcom.\n            line 184: è stata inserito un duplicato della CWBindingSetQosValues() per la cross compilazione per la chiamata delle funzioni\n                 set_wme_* che agiscono sui driver Broadcom.\nWTPBinding.h        : n/c\nWTP.c           : n/c\nWTPConfigFile.c     : n/c\nWTPConfigureState.c : n/c\nWTPDataCheckState.c : n/c\nWTPDiscoveryState.c : n/c\nWTPDriverInteraction.c  : n/c\nWTPFrameReceive.c   : n/c\nWTPFrameReceive.h   : n/c\nWTPJoinState.c      : n/c\nWTPProtocol.c       line 98: è stata aggiunta l'implementazione della funzione CWAssembleMsgElemDataTransferData() per l'asemblaggio del msg                    elements Data presente nel messaggio capwap DataTransfer\n            line 806: implementazione della funzione CWParseAddStation() per il parsing del msg element AddStation.\n\nWTPProtocol.h       line 93: aggiunta del prototipo della funzione CWAssembleMsgElemDataTransferData();\n            line 115: aggiunta del prototipo della funzione CWParseAddStation();\nWTPProtocol_User.c  : n/c\nWTPRetransmission.c : n/c\nWTPRunState.c       line 66: aggiunta del prototipo della funzione CWSaveClearConfigurationRequest();\n            line 68: aggiunta del prototipo della funzione CWAssembleClearConfigurationResponse();\n            line 74: aggiunta del prototipo della funzione CWAssembleStationConfigurationResponse();\n            line 80: aggiunta del prototipo della funzione CWParseStationConfigurationRequest();\n            line 270: è stato aggiunto il case CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_REQUEST per gestire il msg di ClearConfigurationRequest\n            line 285: è stato aggiunto il case CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_REQUEST per gestire il msg di                     StationConfigurationRequest\n            line 568: è stata aggiunta l'implementazione della CWAssembleWTPDataTransferRequest() per l'assemblaggio del msg                     DataTransferRequest.\n            line 785: è stata aggiunta l'implementazione della CWAssembleClearConfigurationResponse()per l'assemblaggio della risposta ad                    un ClearConfigurationRequest\n            line 825: è stata aggiunta l'implementazione della CWAssembleStationConfigurationResponse()per l'assemblaggio della risposta ad                      uno StationConfigurationRequest\n            line 923: è stata aggiunta l'implementazione della CWParseStationConfigurationRequest() per il parsing di un msg di                      StationConfigurationRequest\n            line 1040: implementazione della CWSaveClearConfigurationRequest();\nWTPRunStateCheck.c  : n/c\nWTPSettingsFile.c   : n/c\nWTPSulkingState.c   : n/c\n\n\n"
  },
  {
    "path": "modifiche_uci_frequency_2009.txt",
    "content": "Capwap README 2009: Uci - Frequency\n\n    \nDISCLAIMER: If you want to realize new capabilities into the OpenCapwap Protocol, you need to read the IETF draft writed by CAPWAP Working Group and ACAppsProtocol.h (inside Capwap directoy) first, then you need to modify the Application server which we talk about below is just a way of centering application development, it's not meant to bypass coding in the OpenCapwap code base (many message elements are still missing, so you may have to implement some new ones). \n\nAC side:\n\n    - All sockets, previously Unix sockets, are now Inet sockets.\n\n    To let the Access Controller receive multiple connections from other applications (the ones which add fuctionality), we added to \n    ACInterface a multi-thread TCP server. This TCP server provides to external applications the possibility to talk to the connected\n    Wireless Termination Points tunnelling packets through the Capwap protocol.\n    \n    When the AC server is started, a standalone thread is spawned to manage the various applications' requests. \n    Every time the TCP server receives a new connection, a new thread is spawned to manage that one specific external application.\n    The communication between the AC (through the TCP server) and external applications is ruled by a protocol which (we hope) will\n    be used for every other application (even those which are not yet implemented) as is. This simple protocol is basically made of \n    the command id, the WTP id, the length of the attached payload and the payload itself (refer to ACAppsProtocol.h for header specs).\n    The protocol's main commands are LIST_MSG and CONF_UPDATE_MSG:\n        LIST_MSG returns the list of the WTPs attached to the AC\n        CONF_UPDATE_MSG lets the application send a Capwap Configuration Update Request Message to a single (or all) connected WTP. \n\n    \n    At the moment, implemented Configuration Update Request/Response message elements are:\n        - OFDM Element Type ( Binding 802.11 ) \n        - Vendor Specific Payload Type \n\n    *** All other element types are NOT yet implemented in the OpenCapwap protocol (except those already implemented)\n\n        \n\nWTP side:\n\n    Frequencies Management:\n        To realize Frequencies management inside Capwap WTP we added an additional parsing of Configuration Update Request Message \n        (inside code of 802.11 Binding) with Orthogonal Frequency Division Multiplexing (OFDM) Element Type. (This message, \n        when sent by AC, force the WTP to adhere to received values).\n\n        When a new OFDM message is received, the WTP provide to forward it, through an inet socket (udp), to an external application\n        that will do the corrispondent operations (scanning, monitoring, setting).\n        We added a new thread too (WTPFreqStatsReceive) inside WTP that receive the statistics packets (or ack packet, for frequency \n        setting operation) and provide to encapsulate them in CAPWAP Data Message that will recognize by AC through an apposite flag\n        (for more informations see CWBinding.h).\n\n\n    Remote UCI command execution via Vendor Specific Payload:\n        OpenCapwap was used to deploy basic remote administration and configuration to a number of access points. The access points\n        use OpenWrt (http://openwrt.org/) running the OpenCapwap WTP daemon. Since OpenWrt comes with a very handy, centralized \n        configuration utility called UCI, custom Vendor Specific Payloads have been coded to implement Uci Vendor Specific Payloads.\n        These custom payloads basically carry uci commands to be executed on one or more wtps (the access points). When the AC issues \n        a Configuration Update Request containing an Uci Vendor Specific Payload to a WTP, the WTP daemon unpacks it and forwards the\n        command to be executed to an external application. The WTP daemon and the external application talk through an inet socket (udp).\n        The external application basically executes the command and signals back the daemon if the command succeded/failed. The WTP \n        daemon then forwards this response to the AC via a Configuration Update Response carrying an Uci Vendor Specific Payload.\n        (For more information see CWVendorPayloads.h)\n        These messages have all been handled by some new code which is completely separated from the 802.11 Binding Code. This code \n        is essentially meant to manage Capwap Protocol Element Types (which couldn't be treated as part of a specific Technology Binding). \n"
  },
  {
    "path": "os.h",
    "content": "/*\n * OS specific functions\n * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n *\n * Alternatively, this software may be distributed under the terms of BSD\n * license.\n *\n * See README and COPYING for more details.\n */\n\n#ifndef OS_H\n#define OS_H\n\ntypedef long os_time_t;\n\n/**\n * os_sleep - Sleep (sec, usec)\n * @sec: Number of seconds to sleep\n * @usec: Number of microseconds to sleep\n */\nvoid os_sleep(os_time_t sec, os_time_t usec);\n\nstruct os_time {\n\tos_time_t sec;\n\tos_time_t usec;\n};\n\n/**\n * os_get_time - Get current time (sec, usec)\n * @t: Pointer to buffer for the time\n * Returns: 0 on success, -1 on failure\n */\nint os_get_time(struct os_time *t);\n\n/* Helper macros for handling struct os_time */\n\n#define os_time_before(a, b) \\\n    ((a)->sec < (b)->sec || \\\n     ((a)->sec == (b)->sec && (a)->usec < (b)->usec))\n\n#define os_time_sub(a, b, res) do { \\\n    (res)->sec = (a)->sec - (b)->sec; \\\n    (res)->usec = (a)->usec - (b)->usec; \\\n    if ((res)->usec < 0) { \\\n        (res)->sec--; \\\n        (res)->usec += 1000000; \\\n    } \\\n} while (0)\n\n/**\n * os_mktime - Convert broken-down time into seconds since 1970-01-01\n * @year: Four digit year\n * @month: Month (1 .. 12)\n * @day: Day of month (1 .. 31)\n * @hour: Hour (0 .. 23)\n * @min: Minute (0 .. 59)\n * @sec: Second (0 .. 60)\n * @t: Buffer for returning calendar time representation (seconds since\n * 1970-01-01 00:00:00)\n * Returns: 0 on success, -1 on failure\n *\n * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time\n * which is used by POSIX mktime().\n */\nint os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t * t);\n\nstruct os_tm {\n\tint sec;\t\t/* 0..59 or 60 for leap seconds */\n\tint min;\t\t/* 0..59 */\n\tint hour;\t\t/* 0..23 */\n\tint day;\t\t/* 1..31 */\n\tint month;\t\t/* 1..12 */\n\tint year;\t\t/* Four digit year */\n};\n\nint os_gmtime(os_time_t t, struct os_tm *tm);\n\n/**\n * os_daemonize - Run in the background (detach from the controlling terminal)\n * @pid_file: File name to write the process ID to or %NULL to skip this\n * Returns: 0 on success, -1 on failure\n */\nint os_daemonize(const char *pid_file);\n\n/**\n * os_daemonize_terminate - Stop running in the background (remove pid file)\n * @pid_file: File name to write the process ID to or %NULL to skip this\n */\nvoid os_daemonize_terminate(const char *pid_file);\n\n/**\n * os_get_random - Get cryptographically strong pseudo random data\n * @buf: Buffer for pseudo random data\n * @len: Length of the buffer\n * Returns: 0 on success, -1 on failure\n */\nint os_get_random(unsigned char *buf, size_t len);\n\n/**\n * os_random - Get pseudo random value (not necessarily very strong)\n * Returns: Pseudo random value\n */\nunsigned long os_random(void);\n\n/**\n * os_rel2abs_path - Get an absolute path for a file\n * @rel_path: Relative path to a file\n * Returns: Absolute path for the file or %NULL on failure\n *\n * This function tries to convert a relative path of a file to an absolute path\n * in order for the file to be found even if current working directory has\n * changed. The returned value is allocated and caller is responsible for\n * freeing it. It is acceptable to just return the same path in an allocated\n * buffer, e.g., return strdup(rel_path). This function is only used to find\n * configuration files when os_daemonize() may have changed the current working\n * directory and relative path would be pointing to a different location.\n */\nchar *os_rel2abs_path(const char *rel_path);\n\n/**\n * os_program_init - Program initialization (called at start)\n * Returns: 0 on success, -1 on failure\n *\n * This function is called when a programs starts. If there are any OS specific\n * processing that is needed, it can be placed here. It is also acceptable to\n * just return 0 if not special processing is needed.\n */\nint os_program_init(void);\n\n/**\n * os_program_deinit - Program deinitialization (called just before exit)\n *\n * This function is called just before a program exists. If there are any OS\n * specific processing, e.g., freeing resourced allocated in os_program_init(),\n * it should be done here. It is also acceptable for this function to do\n * nothing.\n */\nvoid os_program_deinit(void);\n\n/**\n * os_setenv - Set environment variable\n * @name: Name of the variable\n * @value: Value to set to the variable\n * @overwrite: Whether existing variable should be overwritten\n * Returns: 0 on success, -1 on error\n *\n * This function is only used for wpa_cli action scripts. OS wrapper does not\n * need to implement this if such functionality is not needed.\n */\nint os_setenv(const char *name, const char *value, int overwrite);\n\n/**\n * os_unsetenv - Delete environent variable\n * @name: Name of the variable\n * Returns: 0 on success, -1 on error\n *\n * This function is only used for wpa_cli action scripts. OS wrapper does not\n * need to implement this if such functionality is not needed.\n */\nint os_unsetenv(const char *name);\n\n/**\n * os_readfile - Read a file to an allocated memory buffer\n * @name: Name of the file to read\n * @len: For returning the length of the allocated buffer\n * Returns: Pointer to the allocated buffer or %NULL on failure\n *\n * This function allocates memory and reads the given file to this buffer. Both\n * binary and text files can be read with this function. The caller is\n * responsible for freeing the returned buffer with os_free().\n */\nchar *os_readfile(const char *name, size_t * len);\n\n/**\n * os_zalloc - Allocate and zero memory\n * @size: Number of bytes to allocate\n * Returns: Pointer to allocated and zeroed memory or %NULL on failure\n *\n * Caller is responsible for freeing the returned buffer with os_free().\n */\nvoid *os_zalloc(size_t size);\n\n/*\n * The following functions are wrapper for standard ANSI C or POSIX functions.\n * By default, they are just defined to use the standard function name and no\n * os_*.c implementation is needed for them. This avoids extra function calls\n * by allowing the C pre-processor take care of the function name mapping.\n *\n * If the target system uses a C library that does not provide these functions,\n * build_config.h can be used to define the wrappers to use a different\n * function name. This can be done on function-by-function basis since the\n * defines here are only used if build_config.h does not define the os_* name.\n * If needed, os_*.c file can be used to implement the functions that are not\n * included in the C library on the target system. Alternatively,\n * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case\n * these functions need to be implemented in os_*.c file for the target system.\n */\n\n#ifdef OS_NO_C_LIB_DEFINES\n\n/**\n * os_malloc - Allocate dynamic memory\n * @size: Size of the buffer to allocate\n * Returns: Allocated buffer or %NULL on failure\n *\n * Caller is responsible for freeing the returned buffer with os_free().\n */\nvoid *os_malloc(size_t size);\n\n/**\n * os_realloc - Re-allocate dynamic memory\n * @ptr: Old buffer from os_malloc() or os_realloc()\n * @size: Size of the new buffer\n * Returns: Allocated buffer or %NULL on failure\n *\n * Caller is responsible for freeing the returned buffer with os_free().\n * If re-allocation fails, %NULL is returned and the original buffer (ptr) is\n * not freed and caller is still responsible for freeing it.\n */\nvoid *os_realloc(void *ptr, size_t size);\n\n/**\n * os_free - Free dynamic memory\n * @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL\n */\nvoid os_free(void *ptr);\n\n/**\n * os_memcpy - Copy memory area\n * @dest: Destination\n * @src: Source\n * @n: Number of bytes to copy\n * Returns: dest\n *\n * The memory areas src and dst must not overlap. os_memmove() can be used with\n * overlapping memory.\n */\nvoid *os_memcpy(void *dest, const void *src, size_t n);\n\n/**\n * os_memmove - Copy memory area\n * @dest: Destination\n * @src: Source\n * @n: Number of bytes to copy\n * Returns: dest\n *\n * The memory areas src and dst may overlap.\n */\nvoid *os_memmove(void *dest, const void *src, size_t n);\n\n/**\n * os_memset - Fill memory with a constant byte\n * @s: Memory area to be filled\n * @c: Constant byte\n * @n: Number of bytes started from s to fill with c\n * Returns: s\n */\nvoid *os_memset(void *s, int c, size_t n);\n\n/**\n * os_memcmp - Compare memory areas\n * @s1: First buffer\n * @s2: Second buffer\n * @n: Maximum numbers of octets to compare\n * Returns: An integer less than, equal to, or greater than zero if s1 is\n * found to be less than, to match, or be greater than s2. Only first n\n * characters will be compared.\n */\nint os_memcmp(const void *s1, const void *s2, size_t n);\n\n/**\n * os_strdup - Duplicate a string\n * @s: Source string\n * Returns: Allocated buffer with the string copied into it or %NULL on failure\n *\n * Caller is responsible for freeing the returned buffer with os_free().\n */\nchar *os_strdup(const char *s);\n\n/**\n * os_strlen - Calculate the length of a string\n * @s: '\\0' terminated string\n * Returns: Number of characters in s (not counting the '\\0' terminator)\n */\nsize_t os_strlen(const char *s);\n\n/**\n * os_strcasecmp - Compare two strings ignoring case\n * @s1: First string\n * @s2: Second string\n * Returns: An integer less than, equal to, or greater than zero if s1 is\n * found to be less than, to match, or be greatred than s2\n */\nint os_strcasecmp(const char *s1, const char *s2);\n\n/**\n * os_strncasecmp - Compare two strings ignoring case\n * @s1: First string\n * @s2: Second string\n * @n: Maximum numbers of characters to compare\n * Returns: An integer less than, equal to, or greater than zero if s1 is\n * found to be less than, to match, or be greater than s2. Only first n\n * characters will be compared.\n */\nint os_strncasecmp(const char *s1, const char *s2, size_t n);\n\n/**\n * os_strchr - Locate the first occurrence of a character in string\n * @s: String\n * @c: Character to search for\n * Returns: Pointer to the matched character or %NULL if not found\n */\nchar *os_strchr(const char *s, int c);\n\n/**\n * os_strrchr - Locate the last occurrence of a character in string\n * @s: String\n * @c: Character to search for\n * Returns: Pointer to the matched character or %NULL if not found\n */\nchar *os_strrchr(const char *s, int c);\n\n/**\n * os_strcmp - Compare two strings\n * @s1: First string\n * @s2: Second string\n * Returns: An integer less than, equal to, or greater than zero if s1 is\n * found to be less than, to match, or be greatred than s2\n */\nint os_strcmp(const char *s1, const char *s2);\n\n/**\n * os_strncmp - Compare two strings\n * @s1: First string\n * @s2: Second string\n * @n: Maximum numbers of characters to compare\n * Returns: An integer less than, equal to, or greater than zero if s1 is\n * found to be less than, to match, or be greater than s2. Only first n\n * characters will be compared.\n */\nint os_strncmp(const char *s1, const char *s2, size_t n);\n\n/**\n * os_strncpy - Copy a string\n * @dest: Destination\n * @src: Source\n * @n: Maximum number of characters to copy\n * Returns: dest\n */\nchar *os_strncpy(char *dest, const char *src, size_t n);\n\n/**\n * os_strstr - Locate a substring\n * @haystack: String (haystack) to search from\n * @needle: Needle to search from haystack\n * Returns: Pointer to the beginning of the substring or %NULL if not found\n */\nchar *os_strstr(const char *haystack, const char *needle);\n\n/**\n * os_snprintf - Print to a memory buffer\n * @str: Memory buffer to print into\n * @size: Maximum length of the str buffer\n * @format: printf format\n * Returns: Number of characters printed (not including trailing '\\0').\n *\n * If the output buffer is truncated, number of characters which would have\n * been written is returned. Since some C libraries return -1 in such a case,\n * the caller must be prepared on that value, too, to indicate truncation.\n *\n * Note: Some C library implementations of snprintf() may not guarantee null\n * termination in case the output is truncated. The OS wrapper function of\n * os_snprintf() should provide this guarantee, i.e., to null terminate the\n * output buffer if a C library version of the function is used and if that\n * function does not guarantee null termination.\n *\n * If the target system does not include snprintf(), see, e.g.,\n * http://www.ijs.si/software/snprintf/ for an example of a portable\n * implementation of snprintf.\n */\nint os_snprintf(char *str, size_t size, const char *format, ...);\n\n#else\t\t\t\t/* OS_NO_C_LIB_DEFINES */\n\n#ifdef WPA_TRACE\nvoid *os_malloc(size_t size);\nvoid *os_realloc(void *ptr, size_t size);\nvoid os_free(void *ptr);\nchar *os_strdup(const char *s);\n#else\t\t\t\t/* WPA_TRACE */\n#ifndef os_malloc\n#define os_malloc(s) malloc((s))\n#endif\n#ifndef os_realloc\n#define os_realloc(p, s) realloc((p), (s))\n#endif\n#ifndef os_free\n#define os_free(p) free((p))\n#endif\n#ifndef os_strdup\n#ifdef _MSC_VER\n#define os_strdup(s) _strdup(s)\n#else\n#define os_strdup(s) strdup(s)\n#endif\n#endif\n#endif\t\t\t\t/* WPA_TRACE */\n\n#ifndef os_memcpy\n#define os_memcpy(d, s, n) memcpy((d), (s), (n))\n#endif\n#ifndef os_memmove\n#define os_memmove(d, s, n) memmove((d), (s), (n))\n#endif\n#ifndef os_memset\n#define os_memset(s, c, n) memset(s, c, n)\n#endif\n#ifndef os_memcmp\n#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n))\n#endif\n\n#ifndef os_strlen\n#define os_strlen(s) strlen(s)\n#endif\n#ifndef os_strcasecmp\n#ifdef _MSC_VER\n#define os_strcasecmp(s1, s2) _stricmp((s1), (s2))\n#else\n#define os_strcasecmp(s1, s2) strcasecmp((s1), (s2))\n#endif\n#endif\n#ifndef os_strncasecmp\n#ifdef _MSC_VER\n#define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n))\n#else\n#define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n))\n#endif\n#endif\n#ifndef os_strchr\n#define os_strchr(s, c) strchr((s), (c))\n#endif\n#ifndef os_strcmp\n#define os_strcmp(s1, s2) strcmp((s1), (s2))\n#endif\n#ifndef os_strncmp\n#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))\n#endif\n#ifndef os_strncpy\n#define os_strncpy(d, s, n) strncpy((d), (s), (n))\n#endif\n#ifndef os_strrchr\n#define os_strrchr(s, c) strrchr((s), (c))\n#endif\n#ifndef os_strstr\n#define os_strstr(h, n) strstr((h), (n))\n#endif\n\n#ifndef os_snprintf\n#ifdef _MSC_VER\n#define os_snprintf _snprintf\n#else\n#define os_snprintf snprintf\n#endif\n#endif\n\n#endif\t\t\t\t/* OS_NO_C_LIB_DEFINES */\n\n/**\n * os_strlcpy - Copy a string with size bound and NUL-termination\n * @dest: Destination\n * @src: Source\n * @siz: Size of the target buffer\n * Returns: Total length of the target string (length of src) (not including\n * NUL-termination)\n *\n * This function matches in behavior with the strlcpy(3) function in OpenBSD.\n */\nsize_t os_strlcpy(char *dest, const char *src, size_t siz);\n\n#ifdef OS_REJECT_C_LIB_FUNCTIONS\n#define malloc OS_DO_NOT_USE_malloc\n#define realloc OS_DO_NOT_USE_realloc\n#define free OS_DO_NOT_USE_free\n#define memcpy OS_DO_NOT_USE_memcpy\n#define memmove OS_DO_NOT_USE_memmove\n#define memset OS_DO_NOT_USE_memset\n#define memcmp OS_DO_NOT_USE_memcmp\n#undef strdup\n#define strdup OS_DO_NOT_USE_strdup\n#define strlen OS_DO_NOT_USE_strlen\n#define strcasecmp OS_DO_NOT_USE_strcasecmp\n#define strncasecmp OS_DO_NOT_USE_strncasecmp\n#undef strchr\n#define strchr OS_DO_NOT_USE_strchr\n#undef strcmp\n#define strcmp OS_DO_NOT_USE_strcmp\n#undef strncmp\n#define strncmp OS_DO_NOT_USE_strncmp\n#undef strncpy\n#define strncpy OS_DO_NOT_USE_strncpy\n#define strrchr OS_DO_NOT_USE_strrchr\n#define strstr OS_DO_NOT_USE_strstr\n#undef snprintf\n#define snprintf OS_DO_NOT_USE_snprintf\n\n#define strcpy OS_DO_NOT_USE_strcpy\n#endif\t\t\t\t/* OS_REJECT_C_LIB_FUNCTIONS */\n\n#endif\t\t\t\t/* OS_H */\n"
  },
  {
    "path": "packages/FC18/x86_64/README.FC18",
    "content": "\nInstallation steps:\n\n1. Flash a firmware with the hostapd-capwap package on a OpenWRT compatible router.\n2. Setup a FC18 box where you want to run AC.\n3. On the FC18 box:\n\t- Copy the RPMS and run: yum -y erase openssl-libs.i686; yum -y install openssl-libs.i686; rpm -ivh --force *.rpm\n\t- Edit /etc/hostapd/hostapd.conf\n\t- Run /etc/init.d/capwap-ac start\n\t- Run /etc/init.d/hostapd start\n4. On the OpenWRT router :\n\t- Run killall -9 hostapd\n\t- Copy /tmp/run/hostapd-phy0.conf to /etc/capwap/hostapd.conf\n\t- Edit the driver in /etc/capwap/hostapd.conf line and set it to capwap_wtp\n\t- Run cd /etc/capwap; WTP; hostapd hostapd.conf\n9. Enjoy the RX_MGMT events flowing trough the radiotap tunnel.\n\nLogs:\n\n- on WTP /var/log/wtp.log.txt\n- on AC /var/log/ac.log.txt\n\nNotes: \n\n- Always run AC first and WTP after otherwise they might get stuck in join state.\n- When hostapd on AC is closed also the hostapd on WTP needs to be closed.\n- When AC and WTP don't talk to eachother because they are stuck in join state\n  allways kill hostapd, AC and WTP processes.\n"
  },
  {
    "path": "root.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDqzCCApOgAwIBAgIJAKFrKBWkidxvMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV\nBAYTAlRXMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxDTALBgNVBAoMBFRPREQxFDAS\nBgNVBAMMC0NBUFdBUF9ST09UMSEwHwYJKoZIhvcNAQkBFhJ0b2RkY2hvdUBnbWFp\nbC5jb20wHhcNMTIwMjI0MTYzNDI0WhcNMzIwMjI0MTYzNDI0WjBsMQswCQYDVQQG\nEwJUVzEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MQ0wCwYDVQQKDARUT0REMRQwEgYD\nVQQDDAtDQVBXQVBfUk9PVDEhMB8GCSqGSIb3DQEJARYSdG9kZGNob3VAZ21haWwu\nY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtGgC6q7ss4Kbcn4H\nfoWNBaXZOp+F/C5kQlsB5aO6k6FGZzij7nJhOpQASR0kSg8TciTPm1eMxn7pIJ7A\nb5raDXnIcRCrpZVEdgAhUPKVkPWRIAhJtjqz6ix2ZrJI2hXjf24kvAzfIwCJgtaP\n0phaUeAUpofzW5PILwiFLrb59oNaMkUxpv6bWHYYQIh5rGf2nVKDZebf+tGEzCxB\njhVVgTfstuTu1tNaQVSR6pTuEoFiOUINLSRfMZ37ajEM+tlK5juETaviT8XMXqMP\nMSAsjwwd3FxmJYi79iNSqmR0/izjlAD/5R/2ZD+0usEhvTR8R0aKbTPvCvU5ZSWL\nMJ8ZPwIDAQABo1AwTjAdBgNVHQ4EFgQUrD4UNtUPiyDVWRbnMfqPtgnNucMwHwYD\nVR0jBBgwFoAUrD4UNtUPiyDVWRbnMfqPtgnNucMwDAYDVR0TBAUwAwEB/zANBgkq\nhkiG9w0BAQUFAAOCAQEAsfmB0z1C8tYE+sRKSTOPKdsVaiwXdOxWkYK++ZyEJR9H\n5zukOQTev5bOQU38JHG7iXMDpSeRwZsaQlJc+/rbn0NDaQa5A3mlQH7EcY7kbxav\nyQ57wHivqUjbQry8oJ5TSvAytb46oJ08zcfVvp4ZPFURTwnf6N9gFibNoBphKPKZ\nl/sRfr+zTPTP2kRFVY2/Jf0VQ8MT+rZFU3mRz2v5pxIrvfhfLheEgySTVBUQ34WE\nMt4a54zhANOt713ZJPeFMM73A46SIJt1rYWzZZ3dyjBREXgXRoeC5myGULMJyLaK\nfZU/B2aHf4uOwOtL/iRuFomKPZwyAK4aMxDEUrp6YA==\n-----END CERTIFICATE-----\n-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,3FC7B4CF6DC46853\n\nLt8A8/KZnD7khLrT10brqWMYg2RQ325Xbi8HQAxcEdfkb15lcucz1eUh4fZ3Fjlf\nK6b63SUXaIY1rr2uVCv3cUMS2L3aZeyJI68rz28jpZ70vEY399MxXeABEGV4YDhe\n/x97rI3EQJ9Q2fnNwoXMd58nFIA5odx7xwv37+3UnDi04bCd0aXs+ejnTpcAVDCS\nERAbjoBxmwc4uwWXcXV2CTpjUham9h1dzb3LHaRYM0uy2rz38WaixlcFbzkh/t97\n/s0L+tiw7N8uwBTsAOF7DxsoB/NXtfaF0FiSnSOdSb8DfXuGH4K1uFZ6XUryyblJ\nExlTwveP2uZVhyFoUBj+x5dcX0YyijunJAizr4ca5piXO4LgIjKrCss2HSO1MNLR\nubLtXFGh/UtQhpBkebbaYC8XHPiFe3BeUyrp3PL+770bF7XfJeH+U3W731Jc2H1t\nWkvNa7UUtKjizaeDY6BRxRCwcYmqKNUwCji2E5KehNii7ErUbqc2zaMAxerzUTdC\nwWw6JdGuRO8jy5Q5QlrBxEaxQUzPxlibe0wFpPp0SKwNwR9CyNhryplTmguhSwbT\nN3/EtSxY3fDz5AWqD/KKy7iqB/l9VZN97uqlVYArdZQ3bmSp991PxWI7zCi+vPYQ\nOaMm7RiRU5ssjjb/xutjYp0iRsf/trbZSfyzEgHzHIk7PsQ/azTc/WhwDjPm0W4h\nCxf+xhgPMLCxfDt46Gr03tw2s3ohcm1czEowY8gctpAMsx3mGROggS6mrQDPlO+9\ngS3Erc8Tn533vYrIVQsYzpLV5UOsc3UHpysc7bBOUUWa4Pcxf6aGxi6EV/BBniKU\nCrptz/crTGe+xtCFYSR9HewHp1eqV1UtBm8nb5If7KddgHTfskGDNsJiTVBpSS1x\nmL8debg3dTzmYgnA7lqQ689DexD6GoqBug7SRUL7dpxfIEL+M+ylbr20kxqDo+Vq\n0pka/SJbIXlnWQxzwKx+6M2e579wAB9dIRKVVm5QzB2L7H6JN2gQ4n9/b/rkaerR\nsLnqNdQQI5ULe3rOnPVJiQj/0IvxnQkZv5fJkRNrWGDrGUp+egzU3cyXL0gYFrXO\nT0wgocPyU/6qfOEGMXJUukgu8id235k+eRRwY3utwPA4gxdTaZmyKtrzjByLUYhU\ngEwbho07Yaifnb0xEBEO/74iCC4A18ig24vNLVF9jsweiB4UpG7rHXKNxDXEdA/d\nPUJbOC3XbtfD20MM3oiPm0H9ZHuOhFmZ981R3Qw3CzGIIZlWC3ntycDxHKM9hxTk\nZafj7PU121263H3buZz8i3BJNf9qBi697PV6UcluVVgqVJsN4gJspmTJgbblwPZW\n2QOg+A2bPNhRBOWXGNPoRnBed36DBS/weR2hmDbZkjpbbYqL1Q964eU3he1Xjrzi\nxVcz6gyjQqatLChakHSliIBOu+PGCjpP5x0ECqh4jyz3KT3CUGY+8iSIGsAt32Cb\neX/1GbaI+GdONVI427N5wY14FRfmvXT04+6FqzOkZGdbCHNi9eqUx+gueTAIm8YX\nPFQv9AIhjM5U4mLmsVvQrf3FVRP/Pq4IkpuSmxv3iJVMPu6vSAjI/Q==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "server.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDaDCCAlCgAwIBAgIJAJI6srPP97u0MA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV\nBAYTAlRXMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxDTALBgNVBAoMBFRPREQxFDAS\nBgNVBAMMC0NBUFdBUF9ST09UMSEwHwYJKoZIhvcNAQkBFhJ0b2RkY2hvdUBnbWFp\nbC5jb20wHhcNMTIwMjI0MTYzNTUzWhcNMjIwMjIxMTYzNTUzWjBfMQswCQYDVQQG\nEwJUVzEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRYwFAYDVQQKDA1DQVBXQVBfU0VS\nVkVSMSEwHwYJKoZIhvcNAQkBFhJ0b2RkY2hvdUBnbWFpbC5jb20wggEiMA0GCSqG\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3AadIRJYKHVOhsk4J/6gSTJSxljSa5MNe\n2pkwZPT0Vi5FUuw7ogTqXfiwutiupxnl1CEX3sDk6j7RlkwY0mnsBwruErlRmeH1\nZkr7kgbfjKcaKhVvJAbfjCOSiYcgi+pGcu1GGTDm9Jkmwy/yKxWW2CBRUGQOrpVa\nrBQobQ5WYmZm66/mBRHwJzLExLWDzZPhNHcSk1H2VxqaTmHzFeSmN4o2HtupCuOE\ndvMzgp+RV87mMBQnQv1FjIoeb3Mqir1wgkcaGWrut+t6uatwRU/vu9tJYuPhpC4N\nD/VmjYnPkR7GFNyncp1ELp2blQls327dTAvjt0gRZCKLxKUGOAh/AgMBAAGjGjAY\nMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUAA4IBAQAdmZA+\n7E0z086Q7ol99z1UQjQ+O5jSdCdwzmekvAru7vsM5Sbbm5ODMyabauKI0nnRRGrX\nISS72BEk5T1I0Nr14YzT8uINnxh/sZWJq1a/hX2/O/YVwfJdSLhCU6oMz1kGaOGG\npNoT7SsVxLUBd61FhTIZp7k8QB3tN/gG4pATv0EnzhQCYASWvRu/Loydeu5XE7WV\nHP6eO1O48l/7CFNW06ilewAURm7Hnnrt7+6HB9bG7Nn9TWoludc54JibrnYw1Q0I\nrLEv+LRBiZtoKqrscJ6/VoD0uBnC2K69yOdbcgcgiykbD6S777c2iwIvtklysIRX\ncHPrByM9nQ/jGHK9\n-----END CERTIFICATE-----\n-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAtwGnSESWCh1TobJOCf+oEkyUsZY0muTDXtqZMGT09FYuRVLs\nO6IE6l34sLrYrqcZ5dQhF97A5Oo+0ZZMGNJp7AcK7hK5UZnh9WZK+5IG34ynGioV\nbyQG34wjkomHIIvqRnLtRhkw5vSZJsMv8isVltggUVBkDq6VWqwUKG0OVmJmZuuv\n5gUR8CcyxMS1g82T4TR3EpNR9lcamk5h8xXkpjeKNh7bqQrjhHbzM4KfkVfO5jAU\nJ0L9RYyKHm9zKoq9cIJHGhlq7rfrermrcEVP77vbSWLj4aQuDQ/1Zo2Jz5EexhTc\np3KdRC6dm5UJbN9u3UwL47dIEWQii8SlBjgIfwIDAQABAoIBAAZRuUwGikPJJXUk\n6grwWAZhvJSxQhnDInfpBnckVU0GmMxuA5g/jPnmysqXeRn2zS8hdw8S8wg0inzE\nOtZ0lZG/4IG+BcYqkSHfKWGsdi5L9g0yPNE8pjwb47KQqyjVi/5ow4azIfwnoA41\nmTc8g59U0TDdnMbhAmlCHeQTd/ZFmpZIygD176nahmYENutV1Y+nm9r9m9FpffCs\nj3Kj7RmjgFx85fQwzLpLKirauVA2RDXCRe0u8xFIH49UmcqkPzFZNeuc/IStVBtp\nHzl9fpLLCIjEcrUlHcfsj+LXFoQ5t/BG59hC3Y5Rk2/awCo8HC2oz4lFaNNt4pGv\nzaDbTiECgYEA53QqVLV7FNBZd+YCnV2SWr4YsoTfounzs4Ro3koP1PRKt7RTerBV\n2H1v8PsxbHibyGMlr6Lu8qpyUoSrC3w5eswbhvHsqF7lZiPfA/+yxDdcb0/JN8cp\nrTqLwR1Yh5XYuMsHTVMmPS5vcUxhBgmeALAzxB6sNAs4puS1I9IxrRECgYEAymor\n/+08p4NU4oP2l1oR8dBIR++da4LLUu4/GEhfkmcU+zugy0xVdl8pzHvdV2qvFOAz\nRBybgez7lBW7rj40/34Bs0fcM2J6FQlWkPjORKVMmyuaaREb8JWd56fIJJRrV51K\naCthUvEUYhuY6vRc33CEoZS+0lE0MZrNEK7inI8CgYEAvTjoXqacAHExo+dEnfjg\n7RTaxiABYYRY+5u1zH3KIbSy3Sss0HIXTM2IVgBW8LJN0e7U4ZmYNoYIvtO9rr8Z\nkv4JRzLD4wbqDq4m5nMGaIpGJK6a9+H4faoOlYvzU627J6C80Ie5DG3JKFxkOfZk\n2XU0bRMSf93oq/Dw8l8mw7ECgYEAogKe2wYgYRduDqt+6J9v83M5F1LDVfTnFqaY\nm6/5xu14zqloRq//S3JZu1B81eYO4o+cmOyozzJGHr3SbWFe/Av4Am4G4p30hvfl\ncL2kIy+HBD+/JE9MZKDsNSmGuTiOPh8oGf52tHM/VFMwbwZNe43MqqOqpB3Yv8de\nUPcZbCMCgYB0Im6UAz6v0j1lPM7P3h8LmHbPiGAUGN5Wx9KmClvmiatxr4EFvX93\nlKry92i809q+CNe3nMWwijoICk1h0w86XXfHo/3GS3GehIPeD9i3lvDZm/iNsG59\nAPP6QvNascmG0mqx/B4xaIqbKz2RUdk+nsob2jhJHbe1g6luYaUFdw==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "settings.ac.txt",
    "content": "# Settings File for AC. Lines beginning with # and blank lines will be ignored\n#\n#\n#\n<CWMIN_VOICE>       2   \n<CWMAX_VOICE>       3\n<AIFS_VOICE>        1\n#\n#\n<CWMIN_VIDEO>       3\n<CWMAX_VIDEO>       4\n<AIFS_VIDEO>        1\n#\n#\n<CWMIN_BEST_EFFORT> 3\n<CWMAX_BEST_EFFORT> 10\n<AIFS_BEST_EFFORT>  2\n#\n#\n<CWMIN_BACKGROUND>  4\n<CWMAX_BACKGROUND>  10\n<AIFS_BACKGROUND>   7\n\n\n<AC_HOSTAPD_PORT> 5543\n<AC_HOSTAPD_UNIX_PATH> /tmp/ac_ipc_hostapd\n\n"
  },
  {
    "path": "settings.wtp.txt",
    "content": "# Settings File for WTP. Lines beginning with # and blank lines will be ignored\n#\n\n#\n<IF_NAME>    mon.wlan0\n<WTP_ETH_IF_NAME>    vmnet1\n<RADIO_0_IF_NAME>    wlan0\n<BASE_MAC_IF_NAME>   vmnet1\n<BOARD_REVISION_NO>   eth0\n<WTP_MODEL_NUM>    12345678\n<WTP_SERIAL_NUM>   12345678\n\n<WTP_HOSTAPD_PORT> 6333\n<WTP_HOSTAPD_UNIX_PATH> /tmp/wtp_ipc_hostapd\n\n\n#<IF_NAME>    mon.wlan0\n#<WTP_ETH_IF_NAME>    eth0\n#<RADIO_0_IF_NAME>    wlan0\n#<BASE_MAC_IF_NAME>   lo\n#<BOARD_REVISION_NO>   eth0\n#<WTP_MODEL_NUM>    12345678\n#<WTP_SERIAL_NUM>   12345678\n\n\n\n"
  },
  {
    "path": "smac_code.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Sotiraq Sima (Sotiraq.Sima@gmail.com)                                         *\n *                                                                                         *\n *******************************************************************************************/\n\n#include <linux/types.h>\n#ifndef AC\ntypedef unsigned char u8;\ntypedef unsigned short u16;\ntypedef unsigned int u32;\n#endif\n\nenum {\n\tERROR = 0,\n\n\tCLOSE = 1,\n\n\tPING = 2,\t\t//  [2]ping\n\tPONG = 3,\t\t//  [3]pong\n\n\t/* only WTP */\n\n\tSTART_WLAN = 4,\n\tSTART_WLAN_R = 5,\n\n\tSTOP_WLAN = 6,\n\tSTOP_WLAN_R = 7,\n\n\tSET_FREQ = 8,\t\t// FREQ sec_channel_offset ht_enabled channel MODE  ex. \"[8]2462 0 0 11 0\"\n\tSET_FREQ_R = 9,\t\t// 0 or 1  ex. \"[9]0\"\n\n\tGET_FREQ = 10,\t\t// ex. \"[10]\"\n\tGET_FREQ_R = 11,\t// ex. \"[11]2462 0 0 11 0\"\n\n\tSET_FRAG = 12,\t\t// Typically the range used for fragmentation threshold is 256-2346 (-1 == off) ex. \"[12]2000\"\n\tSET_FRAG_R = 13,\t// ex. \"[13]0\"\n\n\tGET_FRAG = 14,\t\t// ex. \"[14]\"   (-1 == off)\n\tGET_FRAG_R = 15,\t// ex. \"[15]2000\"\n\n\tSET_BITRATE = 16,\n\tSET_BITRATE_R = 17,\n\n\tGET_BITRATE = 18,\n\tGET_BITRATE_R = 19,\n\n\tSET_RTS = 20,\t\t// 0-2347 (-1 == off)  ex. \"[20]100\"  (-1 == off)\n\tSET_RTS_R = 21,\t\t// ex. \"[21]0\"\n\n\tGET_RTS = 22,\t\t// ex. \"]22]\"  (-1 == off)\n\tGET_RTS_R = 23,\t\t// ex. \"[23]100\"\n\n\tSET_TXPOWER = 24,\n\tSET_TXPOWER_R = 25,\n\n\tGET_TXPOWER = 26,\n\tGET_TXPOWER_R = 27,\n\n\t/*\n\t * VO - 0  CWMIN:3  CWMAX:7  AIFS:2\n\t * VI - 1  CWMIN:7  CWMAX:15  AIFS:2\n\t * BE - 2  CWMIN:15  CWMAX:1023  AIFS:3\n\t * BK - 3  CWMIN:15  CWMAX:1023  AIFS:7\n\t */\n\tSET_TXQ = 28,\n\tSET_TXQ_R = 29,\n\n\tGET_TXQ = 30,\n\tGET_TXQ_R = 31,\n\n\tSET_ADDR = 32,\n\tSET_ADDR_R = 33,\n\n\tDEL_ADDR = 34,\n\tDEL_ADDR_R = 35,\n\n\tADD_WLAN = 36,\n\tADD_WLAN_R = 37,\n\n\tDEL_WLAN = 38,\n\tDEL_WLAN_R = 39,\n\n\tWTPRINFO = 40,\n\tWTPRINFO_R = 41,\n\n\tGET_RATES = 42,\n\tGET_RATES_R = 43,\n\n\tGET_MDC = 44,\n\tGET_MDC_R = 45,\n\n\tSET_WTPRINFO = 46,\n\tSET_WTPRINFO_R = 47,\n\n\tSET_RATES = 48,\n\tSET_RATES_R = 49,\n\n\tSET_MDC = 50,\n\tSET_MDC_R = 51,\n\n\tGOLIVE = 52,\n\tGOLIVE_R = 53,\n\n\tWANT_GOLIVE = 54,\n\tHAVE_TO_WAIT = 55,\n\n\tGET_MAC = 56,\n\tGET_MAC_R = 57,\n\n\tSET_MAC = 58,\n\tSET_MAC_R = 59,\n\n//--------\n\n\tDATE_TO_WTP = 100,\n\tDATE_TO_AC = 101,\n\n\tCONNECT = 102,\n\tCONNECT_R = 103,\n\n\tGOWAITWLAN = 104,\n\tGOWAITWLAN_R = 105,\n\tSEND_WLAN_TO_WTP = 106\n};\n"
  },
  {
    "path": "tap.c",
    "content": "/*\n * Documentation/networking/tuntap.txt\n *\n */\n\n#include \"CWAC.h\"\n#include \"CWVendorPayloads.h\"\n#include \"CWFreqPayloads.h\"\n#include \"WUM.h\"\n\n#include <linux/if_tun.h>\n\n#ifdef DMALLOC\n#include \"../dmalloc-5.5.0/dmalloc.h\"\n#endif\n\nint tun_alloc(char *dev, int flags)\n{\n\n\tstruct ifreq ifr;\n\tint fd, err;\n\tchar *clonedev = \"/dev/net/tun\";\n\n\t/* Arguments taken by the function:\n\t *\n\t * char *dev: the name of an interface (or '\\0'). MUST have enough\n\t *   space to hold the interface name if '\\0' is passed\n\t * int flags: interface flags (eg, IFF_TUN etc.)\n\t */\n\n\t/* open the clone device */\n\tif ((fd = open(clonedev, O_RDWR)) < 0) {\n\t\treturn fd;\n\t}\n\n\t/* preparation of the struct ifr, of type \"struct ifreq\" */\n\tmemset(&ifr, 0, sizeof(ifr));\n\n\tifr.ifr_flags = flags;\t/* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */\n\n\tif (*dev) {\n\t\t/* if a device name was specified, put it in the structure; otherwise,\n\t\t * the kernel will try to allocate the \"next\" device of the\n\t\t * specified type */\n\t\tstrncpy(ifr.ifr_name, dev, IFNAMSIZ);\n\t}\n\n\t/* try to create the device */\n\tif ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) {\n\t\tCWLog(\"Err to creater tap device\");\n\t\tclose(fd);\n\t\treturn err;\n\t}\n\n\t/* if the operation was successful, write back the name of the\n\t * interface to the variable \"dev\", so the caller can know\n\t * it. Note that the caller MUST reserve space in *dev (see calling\n\t * code below) */\n\tstrcpy(dev, ifr.ifr_name);\n\n\t/* this is the special file descriptor that the caller will use to talk\n\t * with the virtual interface */\n\treturn fd;\n}\n\nint init_AC_tap_interface(int WTPIndex)\n{\n\tsprintf(gWTPs[WTPIndex].tap_name, \"wtp%d\", WTPIndex);\n\n\tgWTPs[WTPIndex].tap_fd = tun_alloc(gWTPs[WTPIndex].tap_name, IFF_TAP | IFF_NO_PI);\n\n\tCWDebugLog(\"gWTPs[%d].tap_name %s,tap_fd %d\", WTPIndex, gWTPs[WTPIndex].tap_name, gWTPs[WTPIndex].tap_fd);\n\n\treturn 0;\n}\n"
  },
  {
    "path": "tap.h",
    "content": "/*******************************************************************************************\n * Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *\n *                      Universita' Campus BioMedico - Italy                               *\n *                                                                                         *\n * This program is free software; you can redistribute it and/or modify it under the terms *\n * of the GNU General Public License as published by the Free Software Foundation; either  *\n * version 2 of the License, or (at your option) any later version.                        *\n *                                                                                         *\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY         *\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A         *\n * PARTICULAR PURPOSE. See the GNU General Public License for more details.                *\n *                                                                                         *\n * You should have received a copy of the GNU General Public License along with this       *\n * program; if not, write to the:                                                          *\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,                    *\n * MA  02111-1307, USA.                                                                    *\n *                                                                                         *\n * --------------------------------------------------------------------------------------- *\n * Project:  Capwap                                                                        *\n *                                                                                         *\n * Author :  Ludovico Rossi (ludo@bluepixysw.com)                                          *\n *           Del Moro Andrea (andrea_delmoro@libero.it)                                    *\n *           Giovannini Federica (giovannini.federica@gmail.com)                           *\n *           Massimo Vellucci (m.vellucci@unicampus.it)                                    *\n *           Mauro Bisson (mauro.bis@gmail.com)                                            *\n *******************************************************************************************/\n\n#ifndef __AC_TAP_H__\n#define __AC_TAP_H__\n\nint init_AC_tap_interface(int WTPIndex);\n\n#endif\n"
  },
  {
    "path": "timerlib.c",
    "content": "/*\n * Copyright (C) 2008\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A         *\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\n *\n * Author(s): Mauro Bisson\n */\n\n#include <stdio.h>\t\t/* printf */\n#include <stdlib.h>\n#include <sys/time.h>\n#include <pthread.h>\n#include <errno.h>\t\t/* ETIMEDOUT */\n#include <signal.h>\n#include <string.h>\t\t/* memcpy */\n#include \"timerlib.h\"\n\n/* time to wait the init of ticker thread in timer_init() function */\n#define INIT_WAIT_TIME  5\n\n/* for conversion purpose */\n#define NANO_PER_MICRO  1000\n#define MICRO_PER_SEC   1000000\n\n/* max number of microsecond in a timeval struct */\n#define MAX_USEC    999999\n\n/* microseconds in a millisecond */\n#define ALMOST_NOW  1000\n\n#define TIMER_KIND  ITIMER_REAL\n#define SIG_TO_WAIT SIGALRM\n\n/*\n * evals true if struct timeval t1 defines a time strictly before t2;\n * false otherwise.\n */\n#define TV_LESS_THAN(t1,t2) (((t1).tv_sec < (t2).tv_sec) ||\\\n                (((t1).tv_sec == (t2).tv_sec) &&\\\n                 ((t1).tv_usec < (t2).tv_usec)))\n\n/*\n * Assign struct timeval tgt the time interval between the absolute\n * times t1 and t2.\n * IT IS ASSUMED THAT t1 > t2, use TV_LESS_THAN macro to test it.\n */\n#define TV_MINUS(t1,t2,tgt) if ((t1).tv_usec >= (t2).tv_usec) {\\\n                    (tgt).tv_sec = (t1).tv_sec -\\\n                               (t2).tv_sec;\\\n                    (tgt).tv_usec = (t1).tv_usec -\\\n                                    (t2).tv_usec;\\\n                }\\\n                else {\\\n                    (tgt).tv_sec = (t1).tv_sec -\\\n                               (t2).tv_sec -1;\\\n                    (tgt).tv_usec = (t1).tv_usec +\\\n                        (MAX_USEC - (t2).tv_usec);\\\n                }\n\ntypedef struct timer tl_timer_t;\n\nstatic void timer_free(tl_timer_t * /*t */ );\nstatic void timer_dequeue(tl_timer_t * /*t */ );\nstatic void timer_start(struct timeval * /*abs_to */ );\nstatic void *cronometer(void * /*arg */ );\n\nstruct timer {\n\n\tstruct timeval timeout;\n\tvoid (*handler) (void *);\n\tvoid *handler_arg;\n\tint id;\n\tint in_use;\n\tint cancelled;\n\ttl_timer_t *next;\n\ttl_timer_t *prev;\n};\n\nstatic struct {\n\n\ttl_timer_t *first;\n\ttl_timer_t *last;\n\tpthread_mutex_t mutex;\n\tpthread_cond_t cond;\n\tpthread_t ticker;\n\tint cur_id;\n} timerq;\n\nstatic void timer_free(tl_timer_t * t)\n{\n\n\tif (t == NULL)\n\t\treturn;\n\tfree(t);\n\treturn;\n}\n\nstatic void timer_dequeue(tl_timer_t * t)\n{\n\n\tif (t == NULL)\n\t\treturn;\n\n\tif (t->prev == NULL)\n\t\t/* t is the first of the queue */\n\t\ttimerq.first = t->next;\n\telse\n\t\tt->prev->next = t->next;\n\n\tif (t->next == NULL)\n\t\t/* t is the last of the queue */\n\t\ttimerq.last = t->prev;\n\telse\n\t\tt->next->prev = t->prev;\n\n\ttimer_free(t);\n\treturn;\n}\n\n/*\n * Set a timer with setititmer syscall to expire on abs_to time.\n * The parameter abs_to is an absolute time as those returned with\n * gettimeofday (since epoch).\n * If abs_to refers to a time in the past the timer will be set to\n * expire in 1 millisecond.\n * This function has to be called in a critical section.\n */\nstatic void timer_start(struct timeval *abs_to)\n{\n\n\tstruct itimerval relative = { {0, 0}, {0, 0} };\n\tstruct timeval abs_now;\n\tint rv;\n\n\tif (abs_to == NULL)\n\t\treturn;\n\n\t/* absolute to relative time */\n\tgettimeofday(&abs_now, NULL);\n\tif (TV_LESS_THAN(abs_now, *abs_to)) {\n\t\t/* ok, timeout is in the future */\n\t\tTV_MINUS(*abs_to, abs_now, relative.it_value);\n\t} else {\n\t\t/*\n\t\t * ouch, timeout is in the past! Let's set it\n\t\t * to a very near future value.\n\t\t */\n\t\trelative.it_value.tv_sec = 0;\n\t\trelative.it_value.tv_usec = ALMOST_NOW;\n\t}\n\n\trv = setitimer(TIMER_KIND, &relative, NULL);\n\tif (rv == -1) {\n\t\t/* This should never happen but I dont trust myself */\n\t\tperror(\"setitimer\");\n\t\texit(1);\n\t}\n\n\treturn;\n}\n\nstatic void *cronometer(void *arg)\n{\n\n\tvoid (*hdl) (void *);\n\tvoid *hdl_arg = arg;\t/* keep gcc silent */\n\n\tsigset_t mask;\n\tint sig;\n\n\tsigemptyset(&mask);\n\tsigaddset(&mask, SIG_TO_WAIT);\n\n\t/*\n\t * Set this thread to be cancelled only in the cancellation\n\t * points (pthread_cond_wait() and sigwait()).\n\t */\n\tpthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\n\tpthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);\n\n\t/* signal creator thread of succesful init */\n\tpthread_mutex_lock(&timerq.mutex);\n\tpthread_cond_signal(&timerq.cond);\n\t/* printf(\"\\tTicker thread: inizializzaione compleata\\n\"); */\n\tpthread_mutex_unlock(&timerq.mutex);\n\n\twhile (1) {\n\n\t\tpthread_mutex_lock(&timerq.mutex);\n\n\t\twhile (timerq.first == NULL)\n\t\t\tpthread_cond_wait(&timerq.cond, &timerq.mutex);\n\n\t\ttimer_start(&(timerq.first->timeout));\n\t\ttimerq.first->in_use = 1;\n\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\n\t\t/* wait for a pending SIGALRM */\n\t\tsigwait(&mask, &sig);\n\t\t/*\n\t\t * Poiche' un timer non puo' mai scadere prima del tempo\n\t\t * (semmai dopo), all'uscita della sigwait() timerq.first\n\t\t * punta sempre al tl_timer_t per il quale e' stato ricevuto\n\t\t * il segnale. Nel caso in cui venga aggiunto un timer con\n\t\t * scadenza precedente al tempo di attesa rimasto per il\n\t\t * corrente la funzione timer_add() provvede a risettare il\n\t\t * timer al valore del nuovo, piu' corto, e ad inserire\n\t\t * quest'ultimo come primo della coda.\n\t\t * Se invece il timer corrente viene eliminato con timer_rem()\n\t\t * la struttura non verra' eliminata ma verra' solo settato il\n\t\t * suo flag \"cancelled\" ad 1.\n\t\t */\n\t\tpthread_mutex_lock(&timerq.mutex);\n\n\t\tif (timerq.first->cancelled == 1) {\n\n\t\t\ttimer_dequeue(timerq.first);\n\t\t\tpthread_mutex_unlock(&timerq.mutex);\n\t\t\tcontinue;\n\t\t}\n\t\t/*\n\t\t * we cannot be cancelled while freeing memory and executing\n\t\t * an handler.\n\t\t */\n\t\tpthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);\n\t\thdl = timerq.first->handler;\n\t\thdl_arg = timerq.first->handler_arg;\n\t\ttimer_dequeue(timerq.first);\n\t\t/*\n\t\t * unlock the mutex before executing an handler to avoid\n\t\t * possible deadlock inside it.\n\t\t */\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\n\t\thdl(hdl_arg);\n\t\t/* reset cancel state (cancel type has not  been changed) */\n\t\tpthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\n\t}\n\n\treturn NULL;\n}\n\n/*\n * Initialize the timerq struct, spwan the ticker thread,\n * wait its initialization and return.\n */\nint timer_init()\n{\n\n\tint rv;\n\tstruct timespec ts;\n\tstruct timeval tv;\n\n\trv = pthread_mutex_init(&timerq.mutex, NULL);\n\tif (rv != 0)\n\t\treturn 0;\n\n\trv = pthread_cond_init(&timerq.cond, NULL);\n\tif (rv != 0) {\n\n\t\tpthread_mutex_destroy(&timerq.mutex);\n\t\treturn 0;\n\t}\n\n\ttimerq.first = timerq.last = NULL;\n\ttimerq.cur_id = 0;\n\n\tpthread_mutex_lock(&timerq.mutex);\n\n\trv = pthread_create(&timerq.ticker, NULL, cronometer, NULL);\n\tif (rv != 0) {\n\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\t\tpthread_mutex_destroy(&timerq.mutex);\n\t\tpthread_cond_destroy(&timerq.cond);\n\t\treturn 0;\n\t}\n\n\tgettimeofday(&tv, NULL);\n\tts.tv_sec = tv.tv_sec + INIT_WAIT_TIME;\n\tts.tv_nsec = tv.tv_usec * NANO_PER_MICRO;\n\n\trv = pthread_cond_timedwait(&timerq.cond, &timerq.mutex, &ts);\n\tif (rv != 0) {\n\n\t\tif (rv == ETIMEDOUT) {\n\n\t\t\tpthread_cancel(timerq.ticker);\n\t\t\tpthread_join(timerq.ticker, NULL);\n\t\t}\n\t\tpthread_mutex_destroy(&timerq.mutex);\n\t\tpthread_cond_destroy(&timerq.cond);\n\t\treturn 0;\n\t}\n\n\t/*\n\t * BUG.TRL02\n\t * Here we have to detach the thread in oder to avoid memory leakage.\n\t *\n\t * 16/10/2009 - Donato Capitella\n\t */\n\tpthread_detach(timerq.ticker);\n\n\tpthread_mutex_unlock(&timerq.mutex);\n\n\treturn 1;\n}\n\nvoid timer_destroy()\n{\n\n\ttl_timer_t *t;\n\n\tpthread_cancel(timerq.ticker);\n\tpthread_join(timerq.ticker, NULL);\n\n\tt = timerq.last;\n\twhile (t != NULL) {\n\n\t\ttimerq.last = t->prev;\n\t\ttimer_free(t);\n\t\tt = timerq.last;\n\t}\n\n\tpthread_mutex_destroy(&timerq.mutex);\n\tpthread_cond_destroy(&timerq.cond);\n\n\treturn;\n}\n\nint timer_add(long sec, long usec, void (*hndlr) (void *), void *hndlr_arg)\n{\n\n\tstruct timeval new;\n\ttl_timer_t *tmp = NULL;\n\ttl_timer_t *app = NULL;\n\tint id = 0;\n\n\tif (hndlr == NULL)\n\t\treturn -1;\n\n\t/* ensure timeout is in the future */\n\tif ((sec < 0) || (usec < 0) || ((sec == 0) && (usec == 0)))\n\t\treturn -1;\n\n\tpthread_mutex_lock(&timerq.mutex);\n\n\tapp = (tl_timer_t *) malloc(sizeof(tl_timer_t));\n\tif (app == NULL) {\n\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\t\treturn -1;\n\t}\n\n\t/* relative to absolute time for timer */\n\tgettimeofday(&new, NULL);\n\n\t/* add 10^6 microsecond units to seconds */\n\tnew.tv_sec += sec + (new.tv_usec + usec) / MICRO_PER_SEC;\n\t/* keep microseconds inside allowed range */\n\tnew.tv_usec = (new.tv_usec + usec) % MICRO_PER_SEC;\n\n\tmemcpy(&app->timeout, &new, sizeof(struct timeval));\n\tapp->handler = hndlr;\n\tapp->handler_arg = hndlr_arg;\n\n\tid = timerq.cur_id++;\n\tapp->id = id;\n\tapp->in_use = 0;\n\tapp->cancelled = 0;\n\n\tif (timerq.first == NULL) {\n\t\t/* timer queue empty */\n\t\ttimerq.first = app;\n\t\ttimerq.last = app;\n\t\tapp->prev = NULL;\n\t\tapp->next = NULL;\n\t\tpthread_cond_signal(&timerq.cond);\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\t\treturn id;\n\t}\n\n\t/* there is at least a timer in the queue */\n\ttmp = timerq.first;\n\n\t/* find the first timer that expires before app */\n\twhile (tmp != NULL) {\n\n\t\tif (TV_LESS_THAN(app->timeout, tmp->timeout))\n\t\t\tbreak;\n\n\t\ttmp = tmp->next;\n\t}\n\n\tif (tmp == NULL) {\n\t\t/* app is the longest timer */\n\t\tapp->prev = timerq.last;\n\t\tapp->next = NULL;\n\t\ttimerq.last->next = app;\n\t\ttimerq.last = app;\n\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\t\treturn id;\n\t}\n\n\tif (tmp->prev == NULL) {\n\t\t/* app is the shoprtest timer */\n\t\tapp->prev = NULL;\n\t\tapp->next = tmp;\n\t\ttmp->prev = app;\n\t\ttimerq.first = app;\n\n\t\t/* start app timer */\n\t\tapp->in_use = 1;\n\t\ttmp->in_use = 0;\n\t\ttimer_start(&(timerq.first->timeout));\n\t} else {\n\t\tapp->prev = tmp->prev;\n\t\tapp->next = tmp;\n\t\ttmp->prev->next = app;\n\t\ttmp->prev = app;\n\t}\n\n\tpthread_mutex_unlock(&timerq.mutex);\n\treturn id;\n}\n\nvoid timer_rem(int id, void (*free_arg) (void *))\n{\n\n\ttl_timer_t *t;\n\n\tpthread_mutex_lock(&timerq.mutex);\n\tt = timerq.first;\n\n\t/* look for timer id */\n\twhile (t != NULL) {\n\n\t\tif (t->id == id)\n\t\t\tbreak;\n\t\tt = t->next;\n\t}\n\n\tif (t == NULL) {\n\t\t/* timer id is not in queue (maybe empty) */\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\t\treturn;\n\t}\n\n\tif (t->in_use == 1) {\n\t\t/*\n\t\t * timer id has been already activated, so just set\n\t\t * its \"cancelled\" flag (ticker thread will remove it)\n\t\t */\n\n\t\t/* LE-03-02-2010.01\n\t\t * We have to set handler_arg to NULL, otherwise we\n\t\t * risk to free it more than one time.\n\t\t */\n\t\tif (free_arg) {\n\t\t\tfree_arg(t->handler_arg);\n\t\t\tt->handler_arg = NULL;\n\t\t}\n\t\tt->cancelled = 1;\n\t\tpthread_mutex_unlock(&timerq.mutex);\n\t\treturn;\n\t}\n\n\t/* timer id is in the queue and has not been activated */\n\tif (free_arg)\n\t\tfree_arg(t->handler_arg);\n\ttimer_dequeue(t);\n\n\tpthread_mutex_unlock(&timerq.mutex);\n\treturn;\n}\n\nvoid timer_print()\n{\n\n\ttl_timer_t *t;\n\tint i;\n\n\tpthread_mutex_lock(&timerq.mutex);\n\tfor (t = timerq.first, i = 0; t != NULL; t = t->next, i++) {\n\n\t\tprintf(\"Timer %d: id=<%d>, expire=<%u,%u>, in_use=<%d>, cancelled=<%d>\\n\",\n\t\t       i, t->id, (unsigned int)t->timeout.tv_sec, (unsigned int)t->timeout.tv_usec,\n\t\t       t->in_use, t->cancelled);\n\t}\n\tpthread_mutex_unlock(&timerq.mutex);\n\treturn;\n}\n"
  },
  {
    "path": "timerlib.h",
    "content": "/*\n * Copyright (C) 2008\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A         *\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\n *\n * Author(s): Mauro Bisson\n */\n\n/*\n * This C module implements a simple timer library.\n */\n\n#ifndef TIMERLIB_H\n#define TIMERLIB_H\n\n/*\n * Initializes the timer library. It is important that the calling thread and\n * any other thread in the process block the signal SIGALRM.\n *\n * Return: 1 in case of success; 0 otherwise.\n */\nint timer_init();\n\n/*\n * Tears down any data allocated for the library.\n */\nvoid timer_destroy();\n\n/*\n * Adds a timer to expire \"sec\" seconds + \"usec\" milliseconds after the\n * invocation. When the timer will expire, function \"hndlr\" will be executed\n * with arg \"hndlr_arg\". The id of the timer (>=0) is returned.\n *\n * Return: id>=0 in case of success; -1 in case of error.\n *\n * Remarks: sec and usec must define a future time relative to \"now\". If\n * one is negative or both equal zero the funtion will return -1. The\n * library don't manipulate in any way the address pointed by \"hndlr_arg\",\n * it is responsibility of the calling thread to free any memory, if\n * allocated (a good place is at the end of \"hndlr\" function or when calling\n * \"timer_rem()\" ;).\n * There is no costraint about relative time definition, you can set a two\n * second timer as (sec,usec)=(2,0) or (sec,usec)=(0,2000000).\n * Since this library implementation do not rely on \"sigaction()\" syscall,\n * inside \"hndlr\" it is perfectly legal to call any not signal safe and\n * pthread_* function. The only limitation is that timer_destroy() MUST\n * NOT be called inside hndlr.\n * Note that this fuction can be called inside \"hndlr\" to create\n * \"chain timers\".\n */\nint timer_add(long /*sec */ , long /*usec */ , void (* /*hndlr */ )(void *),\n\t      void * /*hndlr_arg */ );\n\n/*\n * Remove from the queue the timer of identifier \"id\", if it retured\n * from a previous succesful call to timer_add(). The function\n * \"free_arg\" is called with the handler argument specified in \"timer_add\"\n * call. It should be used to free the memory when the timer is destroyed\n * before expiring.\n *\n * Remarks: if \"id\" is a value not returned by timer_add() nothing happens.\n */\nvoid timer_rem(int /*id */ , void (* /*free_arg */ )(void *));\n\n/*\n * Prints the content of the timer queue (do not use, it's for debug purpose).\n */\nvoid timer_print();\n\n#endif\n"
  },
  {
    "path": "wireless_copy.h",
    "content": "/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 18.\n * I have just removed kernel related headers and added some typedefs etc. to\n * make this easier to include into user space programs.\n * Jouni Malinen, 2005-03-12.\n *\n * $Id: wireless_copy.h 1426 2006-02-01 20:07:11Z mrenzmann $\n */\n\n/*\n * This file define a set of standard wireless extensions\n *\n * Version :    19  18.3.05\n *\n * Authors :    Jean Tourrilhes - HPL - <jt@hpl.hp.com>\n * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.\n */\n\n#ifndef _LINUX_WIRELESS_H\n#define _LINUX_WIRELESS_H\n\n/************************** DOCUMENTATION **************************/\n/*\n * Initial APIs (1996 -> onward) :\n * -----------------------------\n * Basically, the wireless extensions are for now a set of standard ioctl\n * call + /proc/net/wireless\n *\n * The entry /proc/net/wireless give statistics and information on the\n * driver.\n * This is better than having each driver having its entry because\n * its centralised and we may remove the driver module safely.\n *\n * Ioctl are used to configure the driver and issue commands.  This is\n * better than command line options of insmod because we may want to\n * change dynamically (while the driver is running) some parameters.\n *\n * The ioctl mechanimsm are copied from standard devices ioctl.\n * We have the list of command plus a structure descibing the\n * data exchanged...\n * Note that to add these ioctl, I was obliged to modify :\n *  # net/core/dev.c (two place + add include)\n *  # net/ipv4/af_inet.c (one place + add include)\n *\n * /proc/net/wireless is a copy of /proc/net/dev.\n * We have a structure for data passed from the driver to /proc/net/wireless\n * Too add this, I've modified :\n *  # net/core/dev.c (two other places)\n *  # include/linux/netdevice.h (one place)\n *  # include/linux/proc_fs.h (one place)\n *\n * New driver API (2002 -> onward) :\n * -------------------------------\n * This file is only concerned with the user space API and common definitions.\n * The new driver API is defined and documented in :\n *  # include/net/iw_handler.h\n *\n * Note as well that /proc/net/wireless implementation has now moved in :\n *  # net/core/wireless.c\n *\n * Wireless Events (2002 -> onward) :\n * --------------------------------\n * Events are defined at the end of this file, and implemented in :\n *  # net/core/wireless.c\n *\n * Other comments :\n * --------------\n * Do not add here things that are redundant with other mechanisms\n * (drivers init, ifconfig, /proc/net/dev, ...) and with are not\n * wireless specific.\n *\n * These wireless extensions are not magic : each driver has to provide\n * support for them...\n *\n * IMPORTANT NOTE : As everything in the kernel, this is very much a\n * work in progress. Contact me if you have ideas of improvements...\n */\n\n/***************************** INCLUDES *****************************/\n\n/* jkm - replaced linux headers with C library headers, added typedefs */\n#if 0\n/* To minimise problems in user space, I might remove those headers\n * at some point. Jean II */\n#include <linux/types.h>\t/* for \"caddr_t\" et al      */\n#include <linux/socket.h>\t/* for \"struct sockaddr\" et al  */\n#include <linux/if.h>\t\t/* for IFNAMSIZ and co... */\n#else\n#include <sys/types.h>\n#include <net/if.h>\ntypedef __uint32_t __u32;\ntypedef __int32_t __s32;\ntypedef __uint16_t __u16;\ntypedef __int16_t __s16;\ntypedef __uint8_t __u8;\n#ifndef __user\n#define __user\n#endif\t\t\t\t/* __user */\n#endif\n\n/***************************** VERSION *****************************/\n/*\n * This constant is used to know the availability of the wireless\n * extensions and to know which version of wireless extensions it is\n * (there is some stuff that will be added in the future...)\n * I just plan to increment with each new version.\n */\n#define WIRELESS_EXT    19\n\n/*\n * Changes :\n *\n * V2 to V3\n * --------\n *  Alan Cox start some incompatibles changes. I've integrated a bit more.\n *  - Encryption renamed to Encode to avoid US regulation problems\n *  - Frequency changed from float to struct to avoid problems on old 386\n *\n * V3 to V4\n * --------\n *  - Add sensitivity\n *\n * V4 to V5\n * --------\n *  - Missing encoding definitions in range\n *  - Access points stuff\n *\n * V5 to V6\n * --------\n *  - 802.11 support (ESSID ioctls)\n *\n * V6 to V7\n * --------\n *  - define IW_ESSID_MAX_SIZE and IW_MAX_AP\n *\n * V7 to V8\n * --------\n *  - Changed my e-mail address\n *  - More 802.11 support (nickname, rate, rts, frag)\n *  - List index in frequencies\n *\n * V8 to V9\n * --------\n *  - Support for 'mode of operation' (ad-hoc, managed...)\n *  - Support for unicast and multicast power saving\n *  - Change encoding to support larger tokens (>64 bits)\n *  - Updated iw_params (disable, flags) and use it for NWID\n *  - Extracted iw_point from iwreq for clarity\n *\n * V9 to V10\n * ---------\n *  - Add PM capability to range structure\n *  - Add PM modifier : MAX/MIN/RELATIVE\n *  - Add encoding option : IW_ENCODE_NOKEY\n *  - Add TxPower ioctls (work like TxRate)\n *\n * V10 to V11\n * ----------\n *  - Add WE version in range (help backward/forward compatibility)\n *  - Add retry ioctls (work like PM)\n *\n * V11 to V12\n * ----------\n *  - Add SIOCSIWSTATS to get /proc/net/wireless programatically\n *  - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space\n *  - Add new statistics (frag, retry, beacon)\n *  - Add average quality (for user space calibration)\n *\n * V12 to V13\n * ----------\n *  - Document creation of new driver API.\n *  - Extract union iwreq_data from struct iwreq (for new driver API).\n *  - Rename SIOCSIWNAME as SIOCSIWCOMMIT\n *\n * V13 to V14\n * ----------\n *  - Wireless Events support : define struct iw_event\n *  - Define additional specific event numbers\n *  - Add \"addr\" and \"param\" fields in union iwreq_data\n *  - AP scanning stuff (SIOCSIWSCAN and friends)\n *\n * V14 to V15\n * ----------\n *  - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg\n *  - Make struct iw_freq signed (both m & e), add explicit padding\n *  - Add IWEVCUSTOM for driver specific event/scanning token\n *  - Add IW_MAX_GET_SPY for driver returning a lot of addresses\n *  - Add IW_TXPOW_RANGE for range of Tx Powers\n *  - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points\n *  - Add IW_MODE_MONITOR for passive monitor\n *\n * V15 to V16\n * ----------\n *  - Increase the number of bitrates in iw_range to 32 (for 802.11g)\n *  - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)\n *  - Reshuffle struct iw_range for increases, add filler\n *  - Increase IW_MAX_AP to 64 for driver returning a lot of addresses\n *  - Remove IW_MAX_GET_SPY because conflict with enhanced spy support\n *  - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and \"struct iw_thrspy\"\n *  - Add IW_ENCODE_TEMP and iw_range->encoding_login_index\n *\n * V16 to V17\n * ----------\n *  - Add flags to frequency -> auto/fixed\n *  - Document (struct iw_quality *)->updated, add new flags (INVALID)\n *  - Wireless Event capability in struct iw_range\n *  - Add support for relative TxPower (yick !)\n *\n * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)\n * ----------\n *  - Add support for WPA/WPA2\n *  - Add extended encoding configuration (SIOCSIWENCODEEXT and\n *    SIOCGIWENCODEEXT)\n *  - Add SIOCSIWGENIE/SIOCGIWGENIE\n *  - Add SIOCSIWMLME\n *  - Add SIOCSIWPMKSA\n *  - Add struct iw_range bit field for supported encoding capabilities\n *  - Add optional scan request parameters for SIOCSIWSCAN\n *  - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA\n *    related parameters (extensible up to 4096 parameter values)\n *  - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,\n *    IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND\n *\n * V18 to V19\n * ----------\n *  - Remove (struct iw_point *)->pointer from events and streams\n *  - Remove header includes to help user space\n *  - Increase IW_ENCODING_TOKEN_MAX from 32 to 64\n *  - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros\n *  - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM\n *  - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros\n */\n\n/**************************** CONSTANTS ****************************/\n\n/* -------------------------- IOCTL LIST -------------------------- */\n\n/* Wireless Identification */\n#define SIOCSIWCOMMIT   0x8B00\t/* Commit pending changes to driver */\n#define SIOCGIWNAME 0x8B01\t/* get name == wireless protocol */\n/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.\n * Common values : \"IEEE 802.11-DS\", \"IEEE 802.11-FH\", \"IEEE 802.11b\"...\n * Don't put the name of your driver there, it's useless. */\n\n/* Basic operations */\n#define SIOCSIWNWID 0x8B02\t/* set network id (pre-802.11) */\n#define SIOCGIWNWID 0x8B03\t/* get network id (the cell) */\n#define SIOCSIWFREQ 0x8B04\t/* set channel/frequency (Hz) */\n#define SIOCGIWFREQ 0x8B05\t/* get channel/frequency (Hz) */\n#define SIOCSIWMODE 0x8B06\t/* set operation mode */\n#define SIOCGIWMODE 0x8B07\t/* get operation mode */\n#define SIOCSIWSENS 0x8B08\t/* set sensitivity (dBm) */\n#define SIOCGIWSENS 0x8B09\t/* get sensitivity (dBm) */\n\n/* Informative stuff */\n#define SIOCSIWRANGE    0x8B0A\t/* Unused */\n#define SIOCGIWRANGE    0x8B0B\t/* Get range of parameters */\n#define SIOCSIWPRIV 0x8B0C\t/* Unused */\n#define SIOCGIWPRIV 0x8B0D\t/* get private ioctl interface info */\n#define SIOCSIWSTATS    0x8B0E\t/* Unused */\n#define SIOCGIWSTATS    0x8B0F\t/* Get /proc/net/wireless stats */\n/* SIOCGIWSTATS is strictly used between user space and the kernel, and\n * is never passed to the driver (i.e. the driver will never see it). */\n\n/* Spy support (statistics per MAC address - used for Mobile IP support) */\n#define SIOCSIWSPY  0x8B10\t/* set spy addresses */\n#define SIOCGIWSPY  0x8B11\t/* get spy info (quality of link) */\n#define SIOCSIWTHRSPY   0x8B12\t/* set spy threshold (spy event) */\n#define SIOCGIWTHRSPY   0x8B13\t/* get spy threshold */\n\n/* Access Point manipulation */\n#define SIOCSIWAP   0x8B14\t/* set access point MAC addresses */\n#define SIOCGIWAP   0x8B15\t/* get access point MAC addresses */\n#define SIOCGIWAPLIST   0x8B17\t/* Deprecated in favor of scanning */\n#define SIOCSIWSCAN 0x8B18\t/* trigger scanning (list cells) */\n#define SIOCGIWSCAN 0x8B19\t/* get scanning results */\n\n/* 802.11 specific support */\n#define SIOCSIWESSID    0x8B1A\t/* set ESSID (network name) */\n#define SIOCGIWESSID    0x8B1B\t/* get ESSID */\n#define SIOCSIWNICKN    0x8B1C\t/* set node name/nickname */\n#define SIOCGIWNICKN    0x8B1D\t/* get node name/nickname */\n/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit\n * within the 'iwreq' structure, so we need to use the 'data' member to\n * point to a string in user space, like it is done for RANGE... */\n\n/* Other parameters useful in 802.11 and some other devices */\n#define SIOCSIWRATE 0x8B20\t/* set default bit rate (bps) */\n#define SIOCGIWRATE 0x8B21\t/* get default bit rate (bps) */\n#define SIOCSIWRTS  0x8B22\t/* set RTS/CTS threshold (bytes) */\n#define SIOCGIWRTS  0x8B23\t/* get RTS/CTS threshold (bytes) */\n#define SIOCSIWFRAG 0x8B24\t/* set fragmentation thr (bytes) */\n#define SIOCGIWFRAG 0x8B25\t/* get fragmentation thr (bytes) */\n#define SIOCSIWTXPOW    0x8B26\t/* set transmit power (dBm) */\n#define SIOCGIWTXPOW    0x8B27\t/* get transmit power (dBm) */\n#define SIOCSIWRETRY    0x8B28\t/* set retry limits and lifetime */\n#define SIOCGIWRETRY    0x8B29\t/* get retry limits and lifetime */\n\n/* Encoding stuff (scrambling, hardware security, WEP...) */\n#define SIOCSIWENCODE   0x8B2A\t/* set encoding token & mode */\n#define SIOCGIWENCODE   0x8B2B\t/* get encoding token & mode */\n/* Power saving stuff (power management, unicast and multicast) */\n#define SIOCSIWPOWER    0x8B2C\t/* set Power Management settings */\n#define SIOCGIWPOWER    0x8B2D\t/* get Power Management settings */\n\n/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).\n * This ioctl uses struct iw_point and data buffer that includes IE id and len\n * fields. More than one IE may be included in the request. Setting the generic\n * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers\n * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers\n * are required to report the used IE as a wireless event, e.g., when\n * associating with an AP. */\n#define SIOCSIWGENIE    0x8B30\t/* set generic IE */\n#define SIOCGIWGENIE    0x8B31\t/* get generic IE */\n\n/* WPA : IEEE 802.11 MLME requests */\n#define SIOCSIWMLME 0x8B16\t/* request MLME operation; uses\n\t\t\t\t * struct iw_mlme */\n/* WPA : Authentication mode parameters */\n#define SIOCSIWAUTH 0x8B32\t/* set authentication mode params */\n#define SIOCGIWAUTH 0x8B33\t/* get authentication mode params */\n\n/* WPA : Extended version of encoding configuration */\n#define SIOCSIWENCODEEXT 0x8B34\t/* set encoding token & mode */\n#define SIOCGIWENCODEEXT 0x8B35\t/* get encoding token & mode */\n\n/* WPA2 : PMKSA cache management */\n#define SIOCSIWPMKSA    0x8B36\t/* PMKSA cache operation */\n\n/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */\n\n/* These 32 ioctl are wireless device private, for 16 commands.\n * Each driver is free to use them for whatever purpose it chooses,\n * however the driver *must* export the description of those ioctls\n * with SIOCGIWPRIV and *must* use arguments as defined below.\n * If you don't follow those rules, DaveM is going to hate you (reason :\n * it make mixed 32/64bit operation impossible).\n */\n#define SIOCIWFIRSTPRIV 0x8BE0\n#define SIOCIWLASTPRIV  0x8BFF\n/* Previously, we were using SIOCDEVPRIVATE, but we now have our\n * separate range because of collisions with other tools such as\n * 'mii-tool'.\n * We now have 32 commands, so a bit more space ;-).\n * Also, all 'odd' commands are only usable by root and don't return the\n * content of ifr/iwr to user (but you are not obliged to use the set/get\n * convention, just use every other two command). More details in iwpriv.c.\n * And I repeat : you are not forced to use them with iwpriv, but you\n * must be compliant with it.\n */\n\n/* ------------------------- IOCTL STUFF ------------------------- */\n\n/* The first and the last (range) */\n#define SIOCIWFIRST 0x8B00\n#define SIOCIWLAST  SIOCIWLASTPRIV\t/* 0x8BFF */\n#define IW_IOCTL_IDX(cmd)   ((cmd) - SIOCIWFIRST)\n\n/* Even : get (world access), odd : set (root access) */\n#define IW_IS_SET(cmd)  (!((cmd) & 0x1))\n#define IW_IS_GET(cmd)  ((cmd) & 0x1)\n\n/* ----------------------- WIRELESS EVENTS ----------------------- */\n/* Those are *NOT* ioctls, do not issue request on them !!! */\n/* Most events use the same identifier as ioctl requests */\n\n#define IWEVTXDROP  0x8C00\t/* Packet dropped to excessive retry */\n#define IWEVQUAL    0x8C01\t/* Quality part of statistics (scan) */\n#define IWEVCUSTOM  0x8C02\t/* Driver specific ascii string */\n#define IWEVREGISTERED  0x8C03\t/* Discovered a new node (AP mode) */\n#define IWEVEXPIRED 0x8C04\t/* Expired a node (AP mode) */\n#define IWEVGENIE   0x8C05\t/* Generic IE (WPA, RSN, WMM, ..)\n\t\t\t\t * (scan results); This includes id and\n\t\t\t\t * length fields. One IWEVGENIE may\n\t\t\t\t * contain more than one IE. Scan\n\t\t\t\t * results may contain one or more\n\t\t\t\t * IWEVGENIE events. */\n#define IWEVMICHAELMICFAILURE 0x8C06\t/* Michael MIC failure\n\t\t\t\t\t * (struct iw_michaelmicfailure)\n\t\t\t\t\t */\n#define IWEVASSOCREQIE  0x8C07\t/* IEs used in (Re)Association Request.\n\t\t\t\t * The data includes id and length\n\t\t\t\t * fields and may contain more than one\n\t\t\t\t * IE. This event is required in\n\t\t\t\t * Managed mode if the driver\n\t\t\t\t * generates its own WPA/RSN IE. This\n\t\t\t\t * should be sent just before\n\t\t\t\t * IWEVREGISTERED event for the\n\t\t\t\t * association. */\n#define IWEVASSOCRESPIE 0x8C08\t/* IEs used in (Re)Association\n\t\t\t\t * Response. The data includes id and\n\t\t\t\t * length fields and may contain more\n\t\t\t\t * than one IE. This may be sent\n\t\t\t\t * between IWEVASSOCREQIE and\n\t\t\t\t * IWEVREGISTERED events for the\n\t\t\t\t * association. */\n#define IWEVPMKIDCAND   0x8C09\t/* PMKID candidate for RSN\n\t\t\t\t * pre-authentication\n\t\t\t\t * (struct iw_pmkid_cand) */\n\n#define IWEVFIRST   0x8C00\n#define IW_EVENT_IDX(cmd)   ((cmd) - IWEVFIRST)\n\n\t\t\t/* ------------------------- PRIVATE INFO ------------------------- */\n\t\t\t/*\n\t\t\t * The following is used with SIOCGIWPRIV. It allow a driver to define\n\t\t\t * the interface (name, type of data) for its private ioctl.\n\t\t\t * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV\n\t\t\t */\n\n#define IW_PRIV_TYPE_MASK   0x7000\t/* Type of arguments */\n#define IW_PRIV_TYPE_NONE   0x0000\n#define IW_PRIV_TYPE_BYTE   0x1000\t/* Char as number */\n#define IW_PRIV_TYPE_CHAR   0x2000\t/* Char as character */\n#define IW_PRIV_TYPE_INT    0x4000\t/* 32 bits int */\n#define IW_PRIV_TYPE_FLOAT  0x5000\t/* struct iw_freq */\n#define IW_PRIV_TYPE_ADDR   0x6000\t/* struct sockaddr */\n\n#define IW_PRIV_SIZE_FIXED  0x0800\t/* Variable or fixed number of args */\n\n#define IW_PRIV_SIZE_MASK   0x07FF\t/* Max number of those args */\n\n\t\t\t/*\n\t\t\t * Note : if the number of args is fixed and the size < 16 octets,\n\t\t\t * instead of passing a pointer we will put args in the iwreq struct...\n\t\t\t */\n\n\t\t\t/* ----------------------- OTHER CONSTANTS ----------------------- */\n\n\t\t\t/* Maximum frequencies in the range struct */\n#define IW_MAX_FREQUENCIES  32\n\t\t\t/* Note : if you have something like 80 frequencies,\n\t\t\t * don't increase this constant and don't fill the frequency list.\n\t\t\t * The user will be able to set by channel anyway... */\n\n\t\t\t/* Maximum bit rates in the range struct */\n#define IW_MAX_BITRATES     32\n\n\t\t\t/* Maximum tx powers in the range struct */\n#define IW_MAX_TXPOWER      8\n\t\t\t/* Note : if you more than 8 TXPowers, just set the max and min or\n\t\t\t * a few of them in the struct iw_range. */\n\n\t\t\t/* Maximum of address that you may set with SPY */\n#define IW_MAX_SPY      8\n\n\t\t\t/* Maximum of address that you may get in the\n\t\t\t   list of access points in range */\n#define IW_MAX_AP       64\n\n\t\t\t/* Maximum size of the ESSID and NICKN strings */\n#define IW_ESSID_MAX_SIZE   32\n\n\t\t\t/* Modes of operation */\n#define IW_MODE_AUTO    0\t/* Let the driver decides */\n#define IW_MODE_ADHOC   1\t/* Single cell network */\n#define IW_MODE_INFRA   2\t/* Multi cell network, roaming, ... */\n#define IW_MODE_MASTER  3\t/* Synchronisation master or Access Point */\n#define IW_MODE_REPEAT  4\t/* Wireless Repeater (forwarder) */\n#define IW_MODE_SECOND  5\t/* Secondary master/repeater (backup) */\n#define IW_MODE_MONITOR 6\t/* Passive monitor (listen only) */\n\n\t\t\t/* Statistics flags (bitmask in updated) */\n#define IW_QUAL_QUAL_UPDATED    0x01\t/* Value was updated since last read */\n#define IW_QUAL_LEVEL_UPDATED   0x02\n#define IW_QUAL_NOISE_UPDATED   0x04\n#define IW_QUAL_ALL_UPDATED 0x07\n#define IW_QUAL_DBM     0x08\t/* Level + Noise are dBm */\n#define IW_QUAL_QUAL_INVALID    0x10\t/* Driver doesn't provide value */\n#define IW_QUAL_LEVEL_INVALID   0x20\n#define IW_QUAL_NOISE_INVALID   0x40\n#define IW_QUAL_ALL_INVALID 0x70\n\n\t\t\t/* Frequency flags */\n#define IW_FREQ_AUTO        0x00\t/* Let the driver decides */\n#define IW_FREQ_FIXED       0x01\t/* Force a specific value */\n\n\t\t\t/* Maximum number of size of encoding token available\n\t\t\t * they are listed in the range structure */\n#define IW_MAX_ENCODING_SIZES   8\n\n\t\t\t/* Maximum size of the encoding token in bytes */\n#define IW_ENCODING_TOKEN_MAX   64\t/* 512 bits (for now) */\n\n\t\t\t/* Flags for encoding (along with the token) */\n#define IW_ENCODE_INDEX     0x00FF\t/* Token index (if needed) */\n#define IW_ENCODE_FLAGS     0xFF00\t/* Flags defined below */\n#define IW_ENCODE_MODE      0xF000\t/* Modes defined below */\n#define IW_ENCODE_DISABLED  0x8000\t/* Encoding disabled */\n#define IW_ENCODE_ENABLED   0x0000\t/* Encoding enabled */\n#define IW_ENCODE_RESTRICTED    0x4000\t/* Refuse non-encoded packets */\n#define IW_ENCODE_OPEN      0x2000\t/* Accept non-encoded packets */\n#define IW_ENCODE_NOKEY     0x0800\t/* Key is write only, so not present */\n#define IW_ENCODE_TEMP      0x0400\t/* Temporary key */\n\n\t\t\t/* Power management flags available (along with the value, if any) */\n#define IW_POWER_ON     0x0000\t/* No details... */\n#define IW_POWER_TYPE       0xF000\t/* Type of parameter */\n#define IW_POWER_PERIOD     0x1000\t/* Value is a period/duration of  */\n#define IW_POWER_TIMEOUT    0x2000\t/* Value is a timeout (to go asleep) */\n#define IW_POWER_MODE       0x0F00\t/* Power Management mode */\n#define IW_POWER_UNICAST_R  0x0100\t/* Receive only unicast messages */\n#define IW_POWER_MULTICAST_R    0x0200\t/* Receive only multicast messages */\n#define IW_POWER_ALL_R      0x0300\t/* Receive all messages though PM */\n#define IW_POWER_FORCE_S    0x0400\t/* Force PM procedure for sending unicast */\n#define IW_POWER_REPEATER   0x0800\t/* Repeat broadcast messages in PM period */\n#define IW_POWER_MODIFIER   0x000F\t/* Modify a parameter */\n#define IW_POWER_MIN        0x0001\t/* Value is a minimum  */\n#define IW_POWER_MAX        0x0002\t/* Value is a maximum */\n#define IW_POWER_RELATIVE   0x0004\t/* Value is not in seconds/ms/us */\n\n\t\t\t/* Transmit Power flags available */\n#define IW_TXPOW_TYPE       0x00FF\t/* Type of value */\n#define IW_TXPOW_DBM        0x0000\t/* Value is in dBm */\n#define IW_TXPOW_MWATT      0x0001\t/* Value is in mW */\n#define IW_TXPOW_RELATIVE   0x0002\t/* Value is in arbitrary units */\n#define IW_TXPOW_RANGE      0x1000\t/* Range of value between min/max */\n\n\t\t\t/* Retry limits and lifetime flags available */\n#define IW_RETRY_ON     0x0000\t/* No details... */\n#define IW_RETRY_TYPE       0xF000\t/* Type of parameter */\n#define IW_RETRY_LIMIT      0x1000\t/* Maximum number of retries */\n#define IW_RETRY_LIFETIME   0x2000\t/* Maximum duration of retries in us */\n#define IW_RETRY_MODIFIER   0x000F\t/* Modify a parameter */\n#define IW_RETRY_MIN        0x0001\t/* Value is a minimum  */\n#define IW_RETRY_MAX        0x0002\t/* Value is a maximum */\n#define IW_RETRY_RELATIVE   0x0004\t/* Value is not in seconds/ms/us */\n\n\t\t\t/* Scanning request flags */\n#define IW_SCAN_DEFAULT     0x0000\t/* Default scan of the driver */\n#define IW_SCAN_ALL_ESSID   0x0001\t/* Scan all ESSIDs */\n#define IW_SCAN_THIS_ESSID  0x0002\t/* Scan only this ESSID */\n#define IW_SCAN_ALL_FREQ    0x0004\t/* Scan all Frequencies */\n#define IW_SCAN_THIS_FREQ   0x0008\t/* Scan only this Frequency */\n#define IW_SCAN_ALL_MODE    0x0010\t/* Scan all Modes */\n#define IW_SCAN_THIS_MODE   0x0020\t/* Scan only this Mode */\n#define IW_SCAN_ALL_RATE    0x0040\t/* Scan all Bit-Rates */\n#define IW_SCAN_THIS_RATE   0x0080\t/* Scan only this Bit-Rate */\n\t\t\t/* struct iw_scan_req scan_type */\n#define IW_SCAN_TYPE_ACTIVE 0\n#define IW_SCAN_TYPE_PASSIVE 1\n\t\t\t/* Maximum size of returned data */\n#define IW_SCAN_MAX_DATA    4096\t/* In bytes */\n\n\t\t\t/* Max number of char in custom event - use multiple of them if needed */\n#define IW_CUSTOM_MAX       256\t/* In bytes */\n\n\t\t\t/* Generic information element */\n#define IW_GENERIC_IE_MAX   1024\n\n\t\t\t/* MLME requests (SIOCSIWMLME / struct iw_mlme) */\n#define IW_MLME_DEAUTH      0\n#define IW_MLME_DISASSOC    1\n\n\t\t\t/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */\n#define IW_AUTH_INDEX       0x0FFF\n#define IW_AUTH_FLAGS       0xF000\n\t\t\t/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)\n\t\t\t * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the\n\t\t\t * parameter that is being set/get to; value will be read/written to\n\t\t\t * struct iw_param value field) */\n#define IW_AUTH_WPA_VERSION     0\n#define IW_AUTH_CIPHER_PAIRWISE     1\n#define IW_AUTH_CIPHER_GROUP        2\n#define IW_AUTH_KEY_MGMT        3\n#define IW_AUTH_TKIP_COUNTERMEASURES    4\n#define IW_AUTH_DROP_UNENCRYPTED    5\n#define IW_AUTH_80211_AUTH_ALG      6\n#define IW_AUTH_WPA_ENABLED     7\n#define IW_AUTH_RX_UNENCRYPTED_EAPOL    8\n#define IW_AUTH_ROAMING_CONTROL     9\n#define IW_AUTH_PRIVACY_INVOKED     10\n\n\t\t\t/* IW_AUTH_WPA_VERSION values (bit field) */\n#define IW_AUTH_WPA_VERSION_DISABLED    0x00000001\n#define IW_AUTH_WPA_VERSION_WPA     0x00000002\n#define IW_AUTH_WPA_VERSION_WPA2    0x00000004\n\n\t\t\t/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */\n#define IW_AUTH_CIPHER_NONE 0x00000001\n#define IW_AUTH_CIPHER_WEP40    0x00000002\n#define IW_AUTH_CIPHER_TKIP 0x00000004\n#define IW_AUTH_CIPHER_CCMP 0x00000008\n#define IW_AUTH_CIPHER_WEP104   0x00000010\n\n\t\t\t/* IW_AUTH_KEY_MGMT values (bit field) */\n#define IW_AUTH_KEY_MGMT_802_1X 1\n#define IW_AUTH_KEY_MGMT_PSK    2\n\n\t\t\t/* IW_AUTH_80211_AUTH_ALG values (bit field) */\n#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001\n#define IW_AUTH_ALG_SHARED_KEY  0x00000002\n#define IW_AUTH_ALG_LEAP    0x00000004\n\n\t\t\t/* IW_AUTH_ROAMING_CONTROL values */\n#define IW_AUTH_ROAMING_ENABLE  0\t/* driver/firmware based roaming */\n#define IW_AUTH_ROAMING_DISABLE 1\t/* user space program used for roaming\n\t\t\t\t\t * control */\n\n\t\t\t/* SIOCSIWENCODEEXT definitions */\n#define IW_ENCODE_SEQ_MAX_SIZE  8\n\t\t\t/* struct iw_encode_ext ->alg */\n#define IW_ENCODE_ALG_NONE  0\n#define IW_ENCODE_ALG_WEP   1\n#define IW_ENCODE_ALG_TKIP  2\n#define IW_ENCODE_ALG_CCMP  3\n\t\t\t/* struct iw_encode_ext ->ext_flags */\n#define IW_ENCODE_EXT_TX_SEQ_VALID  0x00000001\n#define IW_ENCODE_EXT_RX_SEQ_VALID  0x00000002\n#define IW_ENCODE_EXT_GROUP_KEY     0x00000004\n#define IW_ENCODE_EXT_SET_TX_KEY    0x00000008\n\n\t\t\t/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */\n#define IW_MICFAILURE_KEY_ID    0x00000003\t/* Key ID 0..3 */\n#define IW_MICFAILURE_GROUP 0x00000004\n#define IW_MICFAILURE_PAIRWISE  0x00000008\n#define IW_MICFAILURE_STAKEY    0x00000010\n#define IW_MICFAILURE_COUNT 0x00000060\t/* 1 or 2 (0 = count not supported)\n\t\t\t\t\t */\n\n\t\t\t/* Bit field values for enc_capa in struct iw_range */\n#define IW_ENC_CAPA_WPA     0x00000001\n#define IW_ENC_CAPA_WPA2    0x00000002\n#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004\n#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008\n\n\t\t\t/* Event capability macros - in (struct iw_range *)->event_capa\n\t\t\t * Because we have more than 32 possible events, we use an array of\n\t\t\t * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */\n#define IW_EVENT_CAPA_BASE(cmd)     ((cmd >= SIOCIWFIRSTPRIV) ? \\\n                     (cmd - SIOCIWFIRSTPRIV + 0x60) : \\\n                     (cmd - SIOCSIWCOMMIT))\n#define IW_EVENT_CAPA_INDEX(cmd)    (IW_EVENT_CAPA_BASE(cmd) >> 5)\n#define IW_EVENT_CAPA_MASK(cmd)     (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))\n\t\t\t/* Event capability constants - event autogenerated by the kernel\n\t\t\t * This list is valid for most 802.11 devices, customise as needed... */\n#define IW_EVENT_CAPA_K_0   (IW_EVENT_CAPA_MASK(0x8B04) | \\\n                 IW_EVENT_CAPA_MASK(0x8B06) | \\\n                 IW_EVENT_CAPA_MASK(0x8B1A))\n#define IW_EVENT_CAPA_K_1   (IW_EVENT_CAPA_MASK(0x8B2A))\n\t\t\t/* \"Easy\" macro to set events in iw_range (less efficient) */\n#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))\n#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }\n\n\t\t\t/****************************** TYPES ******************************/\n\n\t\t\t/* --------------------------- SUBTYPES --------------------------- */\n\t\t\t/*\n\t\t\t *  Generic format for most parameters that fit in an int\n\t\t\t */\nstruct iw_param {\n\t__s32 value;\t\t/* The value of the parameter itself */\n\t__u8 fixed;\t\t/* Hardware should not use auto select */\n\t__u8 disabled;\t\t/* Disable the feature */\n\t__u16 flags;\t\t/* Various specifc flags (if any) */\n};\n\n/*\n *  For all data larger than 16 octets, we need to use a\n *  pointer to memory allocated in user space.\n */\nstruct iw_point {\n\tvoid __user *pointer;\t/* Pointer to the data  (in user space) */\n\t__u16 length;\t\t/* number of fields or size in bytes */\n\t__u16 flags;\t\t/* Optional params */\n};\n\n/*\n *  A frequency\n *  For numbers lower than 10^9, we encode the number in 'm' and\n *  set 'e' to 0\n *  For number greater than 10^9, we divide it by the lowest power\n *  of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...\n *  The power of 10 is in 'e', the result of the division is in 'm'.\n */\nstruct iw_freq {\n\t__s32 m;\t\t/* Mantissa */\n\t__s16 e;\t\t/* Exponent */\n\t__u8 i;\t\t\t/* List index (when in range struct) */\n\t__u8 flags;\t\t/* Flags (fixed/auto) */\n};\n\n/*\n *  Quality of the link\n */\nstruct iw_quality {\n\t__u8 qual;\t\t/* link quality (%retries, SNR,\n\t\t\t\t   %missed beacons or better...) */\n\t__u8 level;\t\t/* signal level (dBm) */\n\t__u8 noise;\t\t/* noise level (dBm) */\n\t__u8 updated;\t\t/* Flags to know if updated */\n};\n\n/*\n *  Packet discarded in the wireless adapter due to\n *  \"wireless\" specific problems...\n *  Note : the list of counter and statistics in net_device_stats\n *  is already pretty exhaustive, and you should use that first.\n *  This is only additional stats...\n */\nstruct iw_discarded {\n\t__u32 nwid;\t\t/* Rx : Wrong nwid/essid */\n\t__u32 code;\t\t/* Rx : Unable to code/decode (WEP) */\n\t__u32 fragment;\t\t/* Rx : Can't perform MAC reassembly */\n\t__u32 retries;\t\t/* Tx : Max MAC retries num reached */\n\t__u32 misc;\t\t/* Others cases */\n};\n\n/*\n *  Packet/Time period missed in the wireless adapter due to\n *  \"wireless\" specific problems...\n */\nstruct iw_missed {\n\t__u32 beacon;\t\t/* Missed beacons/superframe */\n};\n\n/*\n *  Quality range (for spy threshold)\n */\nstruct iw_thrspy {\n\tstruct sockaddr addr;\t/* Source address (hw/mac) */\n\tstruct iw_quality qual;\t/* Quality of the link */\n\tstruct iw_quality low;\t/* Low threshold */\n\tstruct iw_quality high;\t/* High threshold */\n};\n\n/*\n *  Optional data for scan request\n *\n *  Note: these optional parameters are controlling parameters for the\n *  scanning behavior, these do not apply to getting scan results\n *  (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and\n *  provide a merged results with all BSSes even if the previous scan\n *  request limited scanning to a subset, e.g., by specifying an SSID.\n *  Especially, scan results are required to include an entry for the\n *  current BSS if the driver is in Managed mode and associated with an AP.\n */\nstruct iw_scan_req {\n\t__u8 scan_type;\t\t/* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */\n\t__u8 essid_len;\n\t__u8 num_channels;\t/* num entries in channel_list;\n\t\t\t\t * 0 = scan all allowed channels */\n\t__u8 flags;\t\t/* reserved as padding; use zero, this may\n\t\t\t\t * be used in the future for adding flags\n\t\t\t\t * to request different scan behavior */\n\tstruct sockaddr bssid;\t/* ff:ff:ff:ff:ff:ff for broadcast BSSID or\n\t\t\t\t * individual address of a specific BSS */\n\n\t/*\n\t * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using\n\t * the current ESSID. This allows scan requests for specific ESSID\n\t * without having to change the current ESSID and potentially breaking\n\t * the current association.\n\t */\n\t__u8 essid[IW_ESSID_MAX_SIZE];\n\n\t/*\n\t * Optional parameters for changing the default scanning behavior.\n\t * These are based on the MLME-SCAN.request from IEEE Std 802.11.\n\t * TU is 1.024 ms. If these are set to 0, driver is expected to use\n\t * reasonable default values. min_channel_time defines the time that\n\t * will be used to wait for the first reply on each channel. If no\n\t * replies are received, next channel will be scanned after this. If\n\t * replies are received, total time waited on the channel is defined by\n\t * max_channel_time.\n\t */\n\t__u32 min_channel_time;\t/* in TU */\n\t__u32 max_channel_time;\t/* in TU */\n\n\tstruct iw_freq channel_list[IW_MAX_FREQUENCIES];\n};\n\n/* ------------------------- WPA SUPPORT ------------------------- */\n\n/*\n *  Extended data structure for get/set encoding (this is used with\n *  SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*\n *  flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and\n *  only the data contents changes (key data -> this structure, including\n *  key data).\n *\n *  If the new key is the first group key, it will be set as the default\n *  TX key. Otherwise, default TX key index is only changed if\n *  IW_ENCODE_EXT_SET_TX_KEY flag is set.\n *\n *  Key will be changed with SIOCSIWENCODEEXT in all cases except for\n *  special \"change TX key index\" operation which is indicated by setting\n *  key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.\n *\n *  tx_seq/rx_seq are only used when respective\n *  IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal\n *  TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start\n *  TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally\n *  used only by an Authenticator (AP or an IBSS station) to get the\n *  current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and\n *  RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for\n *  debugging/testing.\n */\nstruct iw_encode_ext {\n\t__u32 ext_flags;\t/* IW_ENCODE_EXT_* */\n\t__u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE];\t/* LSB first */\n\t__u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE];\t/* LSB first */\n\tstruct sockaddr addr;\t/* ff:ff:ff:ff:ff:ff for broadcast/multicast\n\t\t\t\t * (group) keys or unicast address for\n\t\t\t\t * individual keys */\n\t__u16 alg;\t\t/* IW_ENCODE_ALG_* */\n\t__u16 key_len;\n\t__u8 key[0];\n};\n\n/* SIOCSIWMLME data */\nstruct iw_mlme {\n\t__u16 cmd;\t\t/* IW_MLME_* */\n\t__u16 reason_code;\n\tstruct sockaddr addr;\n};\n\n/* SIOCSIWPMKSA data */\n#define IW_PMKSA_ADD        1\n#define IW_PMKSA_REMOVE     2\n#define IW_PMKSA_FLUSH      3\n\n#define IW_PMKID_LEN    16\n\nstruct iw_pmksa {\n\t__u32 cmd;\t\t/* IW_PMKSA_* */\n\tstruct sockaddr bssid;\n\t__u8 pmkid[IW_PMKID_LEN];\n};\n\n/* IWEVMICHAELMICFAILURE data */\nstruct iw_michaelmicfailure {\n\t__u32 flags;\n\tstruct sockaddr src_addr;\n\t__u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];\t/* LSB first */\n};\n\n/* IWEVPMKIDCAND data */\n#define IW_PMKID_CAND_PREAUTH   0x00000001\t/* RNS pre-authentication enabled */\nstruct iw_pmkid_cand {\n\t__u32 flags;\t\t/* IW_PMKID_CAND_* */\n\t__u32 index;\t\t/* the smaller the index, the higher the\n\t\t\t\t * priority */\n\tstruct sockaddr bssid;\n};\n\n/* ------------------------ WIRELESS STATS ------------------------ */\n/*\n * Wireless statistics (used for /proc/net/wireless)\n */\nstruct iw_statistics {\n\t__u16 status;\t\t/* Status\n\t\t\t\t * - device dependent for now */\n\n\tstruct iw_quality qual;\t/* Quality of the link\n\t\t\t\t * (instant/mean/max) */\n\tstruct iw_discarded discard;\t/* Packet discarded counts */\n\tstruct iw_missed miss;\t/* Packet missed counts */\n};\n\n/* ------------------------ IOCTL REQUEST ------------------------ */\n/*\n * This structure defines the payload of an ioctl, and is used\n * below.\n *\n * Note that this structure should fit on the memory footprint\n * of iwreq (which is the same as ifreq), which mean a max size of\n * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...\n * You should check this when increasing the structures defined\n * above in this file...\n */\nunion iwreq_data {\n\t/* Config - generic */\n\tchar name[IFNAMSIZ];\n\t/* Name : used to verify the presence of  wireless extensions.\n\t * Name of the protocol/provider... */\n\n\tstruct iw_point essid;\t/* Extended network name */\n\tstruct iw_param nwid;\t/* network id (or domain - the cell) */\n\tstruct iw_freq freq;\t/* frequency or channel :\n\t\t\t\t * 0-1000 = channel\n\t\t\t\t * > 1000 = frequency in Hz */\n\n\tstruct iw_param sens;\t/* signal level threshold */\n\tstruct iw_param bitrate;\t/* default bit rate */\n\tstruct iw_param txpower;\t/* default transmit power */\n\tstruct iw_param rts;\t/* RTS threshold threshold */\n\tstruct iw_param frag;\t/* Fragmentation threshold */\n\t__u32 mode;\t\t/* Operation mode */\n\tstruct iw_param retry;\t/* Retry limits & lifetime */\n\n\tstruct iw_point encoding;\t/* Encoding stuff : tokens */\n\tstruct iw_param power;\t/* PM duration/timeout */\n\tstruct iw_quality qual;\t/* Quality part of statistics */\n\n\tstruct sockaddr ap_addr;\t/* Access point address */\n\tstruct sockaddr addr;\t/* Destination address (hw/mac) */\n\n\tstruct iw_param param;\t/* Other small parameters */\n\tstruct iw_point data;\t/* Other large parameters */\n};\n\n/*\n * The structure to exchange data for ioctl.\n * This structure is the same as 'struct ifreq', but (re)defined for\n * convenience...\n * Do I need to remind you about structure size (32 octets) ?\n */\nstruct iwreq {\n\tunion {\n\t\tchar ifrn_name[IFNAMSIZ];\t/* if name, e.g. \"eth0\" */\n\t} ifr_ifrn;\n\n\t/* Data part (defined just above) */\n\tunion iwreq_data u;\n};\n\n/* -------------------------- IOCTL DATA -------------------------- */\n/*\n *  For those ioctl which want to exchange mode data that what could\n *  fit in the above structure...\n */\n\n/*\n *  Range of parameters\n */\n\nstruct iw_range {\n\t/* Informative stuff (to choose between different interface) */\n\t__u32 throughput;\t/* To give an idea... */\n\t/* In theory this value should be the maximum benchmarked\n\t * TCP/IP throughput, because with most of these devices the\n\t * bit rate is meaningless (overhead an co) to estimate how\n\t * fast the connection will go and pick the fastest one.\n\t * I suggest people to play with Netperf or any benchmark...\n\t */\n\n\t/* NWID (or domain id) */\n\t__u32 min_nwid;\t\t/* Minimal NWID we are able to set */\n\t__u32 max_nwid;\t\t/* Maximal NWID we are able to set */\n\n\t/* Old Frequency (backward compat - moved lower ) */\n\t__u16 old_num_channels;\n\t__u8 old_num_frequency;\n\n\t/* Wireless event capability bitmasks */\n\t__u32 event_capa[6];\n\n\t/* signal level threshold range */\n\t__s32 sensitivity;\n\n\t/* Quality of link & SNR stuff */\n\t/* Quality range (link, level, noise)\n\t * If the quality is absolute, it will be in the range [0 ; max_qual],\n\t * if the quality is dBm, it will be in the range [max_qual ; 0].\n\t * Don't forget that we use 8 bit arithmetics... */\n\tstruct iw_quality max_qual;\t/* Quality of the link */\n\t/* This should contain the average/typical values of the quality\n\t * indicator. This should be the threshold between a \"good\" and\n\t * a \"bad\" link (example : monitor going from green to orange).\n\t * Currently, user space apps like quality monitors don't have any\n\t * way to calibrate the measurement. With this, they can split\n\t * the range between 0 and max_qual in different quality level\n\t * (using a geometric subdivision centered on the average).\n\t * I expect that people doing the user space apps will feedback\n\t * us on which value we need to put in each driver... */\n\tstruct iw_quality avg_qual;\t/* Quality of the link */\n\n\t/* Rates */\n\t__u8 num_bitrates;\t/* Number of entries in the list */\n\t__s32 bitrate[IW_MAX_BITRATES];\t/* list, in bps */\n\n\t/* RTS threshold */\n\t__s32 min_rts;\t\t/* Minimal RTS threshold */\n\t__s32 max_rts;\t\t/* Maximal RTS threshold */\n\n\t/* Frag threshold */\n\t__s32 min_frag;\t\t/* Minimal frag threshold */\n\t__s32 max_frag;\t\t/* Maximal frag threshold */\n\n\t/* Power Management duration & timeout */\n\t__s32 min_pmp;\t\t/* Minimal PM period */\n\t__s32 max_pmp;\t\t/* Maximal PM period */\n\t__s32 min_pmt;\t\t/* Minimal PM timeout */\n\t__s32 max_pmt;\t\t/* Maximal PM timeout */\n\t__u16 pmp_flags;\t/* How to decode max/min PM period */\n\t__u16 pmt_flags;\t/* How to decode max/min PM timeout */\n\t__u16 pm_capa;\t\t/* What PM options are supported */\n\n\t/* Encoder stuff */\n\t__u16 encoding_size[IW_MAX_ENCODING_SIZES];\t/* Different token sizes */\n\t__u8 num_encoding_sizes;\t/* Number of entry in the list */\n\t__u8 max_encoding_tokens;\t/* Max number of tokens */\n\t/* For drivers that need a \"login/passwd\" form */\n\t__u8 encoding_login_index;\t/* token index for login token */\n\n\t/* Transmit power */\n\t__u16 txpower_capa;\t/* What options are supported */\n\t__u8 num_txpower;\t/* Number of entries in the list */\n\t__s32 txpower[IW_MAX_TXPOWER];\t/* list, in bps */\n\n\t/* Wireless Extension version info */\n\t__u8 we_version_compiled;\t/* Must be WIRELESS_EXT */\n\t__u8 we_version_source;\t/* Last update of source */\n\n\t/* Retry limits and lifetime */\n\t__u16 retry_capa;\t/* What retry options are supported */\n\t__u16 retry_flags;\t/* How to decode max/min retry limit */\n\t__u16 r_time_flags;\t/* How to decode max/min retry life */\n\t__s32 min_retry;\t/* Minimal number of retries */\n\t__s32 max_retry;\t/* Maximal number of retries */\n\t__s32 min_r_time;\t/* Minimal retry lifetime */\n\t__s32 max_r_time;\t/* Maximal retry lifetime */\n\n\t/* Frequency */\n\t__u16 num_channels;\t/* Number of channels [0; num - 1] */\n\t__u8 num_frequency;\t/* Number of entry in the list */\n\tstruct iw_freq freq[IW_MAX_FREQUENCIES];\t/* list */\n\t/* Note : this frequency list doesn't need to fit channel numbers,\n\t * because each entry contain its channel index */\n\n\t__u32 enc_capa;\t\t/* IW_ENC_CAPA_* bit field */\n};\n\n/*\n * Private ioctl interface information\n */\n\nstruct iw_priv_args {\n\t__u32 cmd;\t\t/* Number of the ioctl to issue */\n\t__u16 set_args;\t\t/* Type and number of args */\n\t__u16 get_args;\t\t/* Type and number of args */\n\tchar name[IFNAMSIZ];\t/* Name of the extension */\n};\n\n/* ----------------------- WIRELESS EVENTS ----------------------- */\n/*\n * Wireless events are carried through the rtnetlink socket to user\n * space. They are encapsulated in the IFLA_WIRELESS field of\n * a RTM_NEWLINK message.\n */\n\n/*\n * A Wireless Event. Contains basically the same data as the ioctl...\n */\nstruct iw_event {\n\t__u16 len;\t\t/* Real length of this stuff */\n\t__u16 cmd;\t\t/* Wireless IOCTL */\n\tunion iwreq_data u;\t/* IOCTL fixed payload */\n};\n\n/* Size of the Event prefix (including padding and alignement junk) */\n#define IW_EV_LCP_LEN   (sizeof(struct iw_event) - sizeof(union iwreq_data))\n/* Size of the various events */\n#define IW_EV_CHAR_LEN  (IW_EV_LCP_LEN + IFNAMSIZ)\n#define IW_EV_UINT_LEN  (IW_EV_LCP_LEN + sizeof(__u32))\n#define IW_EV_FREQ_LEN  (IW_EV_LCP_LEN + sizeof(struct iw_freq))\n#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))\n#define IW_EV_ADDR_LEN  (IW_EV_LCP_LEN + sizeof(struct sockaddr))\n#define IW_EV_QUAL_LEN  (IW_EV_LCP_LEN + sizeof(struct iw_quality))\n\n/* iw_point events are special. First, the payload (extra data) come at\n * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,\n * we omit the pointer, so start at an offset. */\n#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \\\n              (char *) NULL)\n#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \\\n             IW_EV_POINT_OFF)\n\n#endif\t\t\t\t/* _LINUX_WIRELESS_H */\n"
  },
  {
    "path": "wum/README",
    "content": "WUM - WTP Update Manager\n\nWum (WTP Update Manager) is the command line tool used to send update\nrequests to the WTPs. Of course it is executed on the AC machine and interacts\nwith the AC Interface.\n\nTo compile it, just run 'make'.\n\nFor further details about how to use it, refer to the document WTPUpdateSystem.pdf\nin the docs sub-directory of this source tree.\n"
  },
  {
    "path": "wum/wum.c",
    "content": "#include <stdio.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <stdlib.h>\n#include <unistd.h>\n\n#include \"wumLib.h\"\n\nvoid printWTPList(struct WTPInfo *wtpList, int nWTPs);\nvoid printVersionHeader();\nvoid printVersionInfo(struct version_info v_info, int wtpId, struct WTPInfo *wtpList);\nvoid printVersionFooter();\nvoid do_version_cmd(int acserver, char *wtpIds, char *wtpNames);\nvoid do_update_cmd(int acserver, char *wtpIds, char *wtpNames, char *cup_path);\nvoid do_cancel_cmd(int acserver, char *wtpIds, char *wtpNames);\nint get_cmd_id(char *cmd);\nchar *WTP_id2name(int id);\nvoid usage(char *name);\n\n#define ACSERVER_ADDRESS \"127.0.0.1\"\n#define ACSERVER_PORT   1235\n\n/* Commands */\n#define CMD_NUM 4\ntypedef struct {\n\tchar id;\n\tconst char *name;\n} cmd_t;\n\nenum { NO_CMD, WTPS_CMD, VERSION_CMD, UPDATE_CMD, CANCEL_CMD };\n\ncmd_t CMDs[] = {\n\t{WTPS_CMD, \"wtps\"},\n\t{VERSION_CMD, \"version\"},\n\t{UPDATE_CMD, \"update\"},\n\t{CANCEL_CMD, \"cancel\"},\n\t{NO_CMD, \"\"}\n};\n\n/* Global WTP List */\nstruct WTPInfo *wtpList;\nint nWTPs;\n\nint main(int argc, char *argv[])\n{\n\tint acserver, wtpId, cmd_id;\n\tvoid *cup;\n\tstruct version_info update_v;\n\tchar *command = NULL, *cup_path = NULL;\n\tchar *wtpIds = NULL, *wtpNames = NULL;\n\tchar *acserver_address = ACSERVER_ADDRESS;\n\tint acserver_port = ACSERVER_PORT;;\n\tint index;\n\tint c;\n\n\topterr = 0;\n\n\t/* Parse options */\n\twhile ((c = getopt(argc, argv, \"ha:p:w:c:f:n:\")) != -1)\n\t\tswitch (c) {\n\t\tcase 'a':\n\t\t\tacserver_address = optarg;\n\t\t\tbreak;\n\t\tcase 'p':\n\t\t\tacserver_port = atoi(optarg);\n\t\t\tbreak;\n\t\tcase 'w':\n\t\t\twtpIds = optarg;\n\t\t\tbreak;\n\t\tcase 'n':\n\t\t\twtpNames = optarg;\n\t\t\tbreak;\n\t\tcase 'c':\n\t\t\tcommand = optarg;\n\t\t\tbreak;\n\t\tcase 'f':\n\t\t\tcup_path = optarg;\n\t\t\tbreak;\n\t\tcase 'h':\n\t\t\tusage(argv[0]);\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\tif (optopt == 'w' || optopt == 'c' || optopt == 'f' || optopt == 'n')\n\t\t\t\tfprintf(stderr, \"Option -%c requires an argument.\\n\", optopt);\n\t\t\telse if (isprint(optopt))\n\t\t\t\tfprintf(stderr, \"Unknown option `-%c'.\\n\", optopt);\n\t\t\telse\n\t\t\t\tfprintf(stderr, \"Unknown option character `\\\\x%x'.\\n\", optopt);\n\t\t\texit(EXIT_FAILURE);\n\t\tdefault:\n\t\t\tusage(argv[0]);\n\t\t\tabort();\n\n\t\t}\n\n\t/* Check arguments */\n\tif (command == NULL) {\n\t\tfprintf(stderr, \"No command specified!\\n\");\n\t\texit(EXIT_FAILURE);\n\t}\n\n\tif ((cmd_id = get_cmd_id(command)) == NO_CMD) {\n\t\tfprintf(stderr, \"Wrong command specified!\");\n\t}\n\n\t/* Connect to server and get WTPs list */\n\tacserver = ACServerConnect(acserver_address, acserver_port);\n\twtpList = ACServerWTPList(acserver, &nWTPs);\n\n\t/* Execute command */\n\tswitch (cmd_id) {\n\tcase WTPS_CMD:\n\t\tprintWTPList(wtpList, nWTPs);\n\t\tbreak;\n\tcase VERSION_CMD:\n\t\tdo_version_cmd(acserver, wtpIds, wtpNames);\n\t\tbreak;\n\tcase UPDATE_CMD:\n\t\tdo_update_cmd(acserver, wtpIds, wtpNames, cup_path);\n\t\tbreak;\n\tcase CANCEL_CMD:\n\t\tdo_cancel_cmd(acserver, wtpIds, wtpNames);\n\t\tbreak;\n\t}\n\n\tfreeWTPList(wtpList, nWTPs);\n\tACServerDisconnect(acserver);\n\n\texit(EXIT_SUCCESS);\n}\n\nint sanitize_wtp_list(int *work_list, int n)\n{\n\tint i, j, z, new_size = n;\n\n\t/* Delete unknown wtp ids */\n\tfor (i = 0; i < new_size; i++) {\n\t\tif (WTP_id2name(work_list[i]) == NULL) {\n\t\t\tfor (j = i; j < new_size - 1; j++) {\n\t\t\t\twork_list[j] = work_list[j + 1];\n\t\t\t}\n\t\t\ti--;\n\t\t\tnew_size--;\n\t\t}\n\t}\n\n\t/* Delete duplicates */\n\tfor (i = 0; i < new_size; i++) {\n\t\tfor (j = i + 1; j < new_size; j++) {\n\t\t\tif (work_list[i] == work_list[j]) {\n\t\t\t\tfor (z = j; z < new_size - 1; z++) {\n\t\t\t\t\twork_list[z] = work_list[z + 1];\n\t\t\t\t}\n\t\t\t\tj--;\n\t\t\t\tnew_size--;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn new_size;\n}\n\nint *all_WTPs()\n{\n\tint *ret, i;\n\n\tret = malloc(nWTPs * sizeof(int));\n\n\tfor (i = 0; i < nWTPs; i++) {\n\t\tret[i] = wtpList[i].wtpId;\n\t}\n\n\treturn ret;\n}\n\nint count_tokens(char *str1, char *str2)\n{\n\tint n = 1;\n\tchar *ptr;\n\n\tif (str1 != NULL)\n\t\tptr = str1;\n\telse if (str2 != NULL)\n\t\tptr = str2;\n\telse\n\t\treturn 0;\n\n\twhile (*ptr != '\\0') {\n\t\tif (*ptr == ',' && *(ptr + 1) != ',' && *(ptr + 1) != '\\0')\n\t\t\tn++;\n\t\tptr++;\n\t}\n\treturn n;\n}\n\nint *get_id_list(char *wtpIds, char *wtpNames, int *n)\n{\n\tchar *token, *ptr;\n\tint *ret = NULL;\n\tint i;\n\n\t*n = count_tokens(wtpIds, wtpNames);\n\n\tif (*n <= 0)\n\t\treturn NULL;\n\n\t/* allocate memory */\n\tret = malloc(*n * sizeof(int));\n\tif (ret == NULL) {\n\t\tperror(\"malloc error!\");\n\t\treturn NULL;\n\t}\n\n\tif (wtpIds != NULL) {\n\t\t/* read ids */\n\t\ttoken = (char *)strtok(wtpIds, \",\");\n\t\tret[0] = atoi(token);\n\n\t\tif (ret[0] == -1)\n\t\t\treturn all_WTPs();\n\n\t\tfor (i = 1; i < *n; i++)\n\t\t\tret[i] = atoi((const char *)strtok(NULL, \",\"));\n\n\t} else {\n\t\t/* read names and convert into ids */\n\t\tfor (i = 0; i < *n; i++) {\n\t\t\tint id;\n\n\t\t\tif (i == 0) {\n\t\t\t\ttoken = (char *)strtok(wtpNames, \",\");\n\t\t\t\tif (strcmp(token, \"all\") == 0)\n\t\t\t\t\treturn all_WTPs();\n\n\t\t\t} else {\n\t\t\t\ttoken = (char *)strtok(NULL, \",\");\n\t\t\t}\n\n\t\t\tif ((id = WTP_name2id(token)) == -1) {\n\t\t\t\tfprintf(stderr, \"%s: specified WTP does not exits\\n\", token);\n\t\t\t}\n\n\t\t\tret[i] = id;\n\t\t}\n\t}\n\n\t/* remove duplicated and unknown WTP ids */\n\t*n = sanitize_wtp_list(ret, *n);\n\n\treturn ret;\n}\n\nvoid do_version_cmd(int acserver, char *wtpIds, char *wtpNames)\n{\n\tint *wtps, n, i;\n\tstruct version_info v_info;\n\n\t/* WTP work list */\n\twtps = get_id_list(wtpIds, wtpNames, &n);\n\n\tif (wtps == NULL) {\n\t\tfprintf(stderr, \"Either a list of wtp ids or wtp names must be specified!\\n\");\n\t\treturn;\n\t}\n\n\tprintVersionHeader();\n\tfor (i = 0; i < n; i++) {\n\t\tWUMGetWTPVersion(acserver, wtps[i], &v_info);\n\t\tprintVersionInfo(v_info, wtps[i], wtpList);\n\t}\n\tprintVersionFooter();\n}\n\nvoid do_update_cmd(int acserver, char *wtpIds, char *wtpNames, char *cup_path)\n{\n\tint *wtps, n, i, ret;\n\tstruct version_info update_v;\n\tvoid *cup;\n\n\tif (cup_path == NULL) {\n\t\tfprintf(stderr, \"In order to execute an update, an update package must be specified! (-f pathname)\\n\");\n\t\treturn;\n\t}\n\n\t/* WTP work list */\n\twtps = get_id_list(wtpIds, wtpNames, &n);\n\tif (wtps == NULL) {\n\t\tfprintf(stderr, \"Either a list of wtp ids or wtp names must be specified!\\n\");\n\t\treturn;\n\t}\n\n\tint fd = open(cup_path, O_RDONLY);\n\tif (fd < 0) {\n\t\tperror(\"open error\");\n\t\treturn;\n\t}\n\n\tif (WUMReadCupVersion(cup_path, &update_v)) {\n\t\treturn;\n\t}\n\n\tcup = mmap(NULL, update_v.size, PROT_READ, MAP_SHARED, fd, 0);\n\tif (cup == NULL) {\n\t\tperror(\"mmap error\");\n\t\treturn;\n\t}\n\n\tprintf(\"*--------*--------------------------------*------------*\\n\");\n\tprintf(\"| %-6s | %-30s | %-10s |\\n\", \"WTP Id\", \"WTp Name\", \"Result\");\n\tprintf(\"*--------*--------------------------------*------------*\\n\");\n\tfor (i = 0; i < n; i++) {\n\t\tret = WUMUpdate(acserver, i, cup, update_v);\n\t\tprintf(\"| %-6d | %-30s | %-10s |\\n\", wtpList[i].wtpId, wtpList[i].name,\n\t\t       (ret == 0) ? \"SUCCESS\" : \"FAILURE\");\n\t}\n\tprintf(\"*--------*--------------------------------*------------*\\n\");\n\n\tmunmap(cup, update_v.size);\n\tclose(fd);\n}\n\nvoid do_cancel_cmd(int acserver, char *wtpIds, char *wtpNames)\n{\n\tint *wtps, n, i;\n\tstruct version_info v_info;\n\n\t/* WTP work list */\n\twtps = get_id_list(wtpIds, wtpNames, &n);\n\n\tif (wtps == NULL) {\n\t\tfprintf(stderr, \"Either a list of wtp ids or wtp names must be specified!\\n\");\n\t\treturn;\n\t}\n\n\tfor (i = 0; i < n; i++) {\n\t\tif (WUMSendCancelRequest(acserver, wtps[i])) {\n\t\t\tfprintf(stderr, \"Error while handling cancel request to WTP %d.\\n\", wtps[i]);\n\t\t} else {\n\t\t\tprintf(\"Cancel request sent for WTP %d\\n\", wtps[i]);\n\t\t}\n\t}\n}\n\nint WTP_name2id(char *name)\n{\n\tint i;\n\n\tfor (i = 0; i < nWTPs; i++) {\n\t\tif (strcmp(name, wtpList[i].name) == 0) {\n\t\t\t/* found WTP! */\n\t\t\treturn wtpList[i].wtpId;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\nchar *WTP_id2name(int id)\n{\n\tint i;\n\n\tfor (i = 0; i < nWTPs; i++) {\n\t\tif (wtpList[i].wtpId == id)\n\t\t\treturn wtpList[i].name;\n\t}\n\n\treturn NULL;\n}\n\nint get_cmd_id(char *cmd)\n{\n\tint i;\n\tfor (i = 0; i < CMD_NUM; i++) {\n\t\tif (strcmp(CMDs[i].name, cmd) == 0)\n\t\t\tbreak;\n\t}\n\n\treturn CMDs[i].id;\n}\n\nvoid printWTPList(struct WTPInfo *wtpList, int nWTPs)\n{\n\tint i;\n\n\tprintf(\"*-------*--------------------------------*\\n\");\n\tprintf(\"| %5s | %-30s |\\n\", \"WTPId\", \"WTPName\");\n\tprintf(\"*-------*--------------------------------*\\n\");\n\tprintf(\"| %5s | %-30s |\\n\", \"-1\", \"all\");\n\n\tif (wtpList != NULL) {\n\t\tfor (i = 0; i < nWTPs; i++) {\n\t\t\tprintf(\"| %5d | %-30s |\\n\", wtpList[i].wtpId, wtpList[i].name);\n\t\t}\n\t}\n\n\tprintf(\"*-------*--------------------------------*\\n\");\n}\n\nvoid printVersionHeader()\n{\n\tprintf(\"*-------*--------------------------------*-----------------*\\n\");\n\tprintf(\"| %5s | %-30s | %-15s |\\n\", \"WTPId\", \"WTPName\", \"Version\");\n\tprintf(\"*-------*--------------------------------*-----------------*\\n\");\n}\n\nvoid printVersionInfo(struct version_info v_info, int wtpId, struct WTPInfo *wtpList)\n{\n\tchar buf[15];\n\tsnprintf(buf, 15, \"%d.%d.%d\", v_info.major, v_info.minor, v_info.revision);\n\tprintf(\"| %5d | %-30s | %-15s |\\n\", wtpList[wtpId].wtpId, wtpList[wtpId].name, buf);\n}\n\nvoid printVersionFooter()\n{\n\tprintf(\"*-------*--------------------------------*-----------------*\\n\");\n}\n\nvoid usage(char *name)\n{\n\tprintf(\"%s -c command [-w id1,...] [-n name1,...] [-f cup_file] [-a address] [-p port]\\n\", name);\n\tprintf(\"\\nAvailable commands:\\n\");\n\tprintf(\"   wtps: list of active wtps.\\n\");\n\tprintf(\"version: version of the specified list of wtps (use -w or -n).\\n\");\n\tprintf(\" update: sends a cup (specified with -f) to the specified list of wtps (use -w or -n).\\n\");\n\tprintf(\" cancel: cancel a pending update on the desired wtps (use -w or -n).\\n\");\n}\n"
  },
  {
    "path": "wum/wumLib.c",
    "content": "#include <stdio.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#include \"wumLib.h\"\n\n#define SA const struct sockaddr\n#define BUF_SIZE 1024\n\nint Readn(int fd, void *ptr, size_t nbytes);\nint Writen(int fd, void *ptr, size_t nbytes);\nvoid readWTPInfo(int acserver, struct WTPInfo *WTPInfo, int pos);\n\ntypedef struct __attribute__ ((__packed__)) {\n\tchar cmd_msg;\n\tchar msg_elem;\n\tint wtpId;\n\tchar wum_type;\n\tint payload_len;\n\tchar *payload;\n} wum_req_t;\n\ntypedef struct {\n\tint wtpId;\n\tint resultCode;\n\tchar wum_type;\n\tint payload_len;\n\tchar *payload;\n\tint offset;\n} wum_resp_t;\n\n#define WUM_INIT_REQ_MSG(msg, size) do { msg.payload_len = 0; msg.payload=malloc(size); } while(0);\n#define WUM_DESTROY_MSG(msg)  do { if (msg.payload_len != 0) free(msg.payload); } while(0);\n\nint Read32(int fd, int *ptr);\nint Write32(int fd, void *ptr);\nint WUMSendMessage(int acserver, wum_req_t msg);\nint WUMReceiveMessage(int acserver, wum_resp_t * msg);\nchar WUMPayloadRetrieve8(wum_resp_t * resp);\nvoid WUMPayloadStore8(wum_req_t * req, char c);\nvoid WUMPayloadStore32(wum_req_t * req, int i);\nvoid WUMPayloadStoreRawBytes(wum_req_t * req, void *buf, int size);\n\n#define MIN(a,b) (a < b) ? (a) : (b)\n\nint ACServerConnect(char *address, int port)\n{\n\tint sockfd, ret;\n\tstruct sockaddr_in servaddr;\n\n\tif ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {\n\t\tperror(\"socket error:\");\n\t\texit(1);\n\t}\n\n\tbzero(&servaddr, sizeof(struct sockaddr_in));\n\tservaddr.sin_family = AF_INET;\n\tservaddr.sin_port = htons(port);\n\tinet_pton(AF_INET, address, &servaddr.sin_addr);\n\n\tif (connect(sockfd, (SA *) & servaddr, sizeof(servaddr)) < 0) {\n\t\tperror(\"connect error:\");\n\t\texit(1);\n\t}\n\n\tif (Read32(sockfd, &ret) != 4) {\n\t\texit(1);\n\t}\n\n\tif (ret == -1) {\n\t\tfprintf(stderr, \"The AC Server's Client Queue Is Currently Full.\\n\");\n\t\texit(1);\n\t} else if (ret != 1) {\n\t\tfprintf(stderr, \"Something Wrong Happened While Connecting To The AC Server.\\n\");\n\t\texit(1);\n\t}\n\n\treturn sockfd;\n}\n\nvoid ACServerDisconnect(int acserver)\n{\n\tchar msg = QUIT_MSG;\n\tif (Writen(acserver, &msg, 1) != 1) {\n\t\tfprintf(stderr, \"Error while sending QUIT message.\\n\");\n\t}\n\n\tif (close(acserver) < 0) {\n\t\tperror(\"close error:\");\n\t}\n}\n\nstruct WTPInfo *ACServerWTPList(int acserver, int *nWTPs)\n{\n\tchar msg = LIST_MSG;\n\tint activeWTPs, i;\n\tstruct WTPInfo *WTPList;\n\n\tif (Writen(acserver, &msg, 1) != 1) {\n\t\tfprintf(stderr, \"Error while sending LIST message.\\n\");\n\t\treturn NULL;\n\t}\n\n\tif (Read32(acserver, &activeWTPs) != 4) {\n\t\tfprintf(stderr, \"Error while receiving WTP Number.\\n\");\n\t\treturn NULL;\n\t}\n\n\tif ((WTPList = malloc(activeWTPs * sizeof(struct WTPInfo))) == NULL) {\n\t\tperror(\"malloc error\");\n\t\treturn NULL;\n\t}\n\n\tfor (i = 0; i < activeWTPs; i++) {\n\t\treadWTPInfo(acserver, WTPList, i);\n\t}\n\n\t*nWTPs = activeWTPs;\n\n\treturn WTPList;\n}\n\nvoid readWTPInfo(int acserver, struct WTPInfo *WTPInfo, int pos)\n{\n\tint nameLen;\n\n\tif (Read32(acserver, &(WTPInfo[pos].wtpId)) != 4) {\n\t\tfprintf(stderr, \"Error while reading wtp index.\\n\");\n\t\tgoto err;\n\t}\n\n\tif (Read32(acserver, &nameLen) != 4) {\n\t\tfprintf(stderr, \"Error while reading wtp name len.\\n\");\n\t\tgoto err;\n\t}\n\n\tif ((WTPInfo[pos].name = malloc(nameLen + 1)) == NULL) {\n\t\tfprintf(stderr, \"Malloc error\\n\");\n\t\tgoto err;\n\t}\n\n\tif (Readn(acserver, WTPInfo[pos].name, nameLen) != nameLen) {\n\t\tfprintf(stderr, \"Error while reading wtp name len.\\n\");\n\t\tgoto err;\n\t}\n\n\tWTPInfo[pos].name[nameLen] = '\\0';\n\treturn;\n\n err:\n\tACServerDisconnect(acserver);\n\texit(1);\n}\n\nvoid freeWTPList(struct WTPInfo *wtpList, int nWTPs)\n{\n\tint i;\n\t/* We do not free the first name, the default one */\n\tfor (i = 0; i < nWTPs; i++) {\n\t\tfree(wtpList[i].name);\n\t}\n\tfree(wtpList);\n}\n\nint WUMGetWTPVersion(int acserver, int wtpId, struct version_info *v_info)\n{\n\twum_req_t msg;\n\twum_resp_t resp;\n\n\tWUM_INIT_REQ_MSG(msg, 0);\n\tmsg.cmd_msg = CONF_UPDATE_MSG;\n\tmsg.msg_elem = MSG_ELEMENT_TYPE_VENDOR_WUM;\n\tmsg.wtpId = wtpId;\n\tmsg.wum_type = WTP_VERSION_REQUEST;\n\n\tif (WUMSendMessage(acserver, msg) != 0) {\n\t\tfprintf(stderr, \"Error while sending WUM message\");\n\t\treturn ERROR;\n\t}\n\n\tif (WUMReceiveMessage(acserver, &resp) != 0) {\n\t\tfprintf(stderr, \"Error while reading response message\");\n\t\treturn ERROR;\n\t}\n\n\tresp.wum_type = WUMPayloadRetrieve8(&resp);\n\tif (resp.wum_type != WTP_VERSION_RESPONSE) {\n\t\tfprintf(stderr, \"Received wrong response message!\");\n\t\treturn ERROR;\n\t}\n\n\tv_info->major = WUMPayloadRetrieve8(&resp);\n\tv_info->minor = WUMPayloadRetrieve8(&resp);\n\tv_info->revision = WUMPayloadRetrieve8(&resp);\n\n\treturn SUCCESS;\n}\n\nvoid StringToLower(char *str)\n{\n\tfor (; *str != '\\0'; str++)\n\t\t*str = tolower(*str);\n}\n\nint WUMReadCupVersion(char *cup_pathname, struct version_info *update_v)\n{\n\tint ret;\n\tchar buf[BUF_SIZE];\n\tchar *token;\n\tstruct stat s_buf;\n\tFILE *cud;\n\n\tsnprintf(buf, BUF_SIZE, \"tar xzf %s -C /tmp update.cud\", cup_pathname);\n\n\tret = system(buf);\n\n\tif (ret != 0)\n\t\treturn ERROR;\n\n\tcud = fopen(\"/tmp/update.cud\", \"r\");\n\tif (cud == NULL) {\n\t\tfprintf(stderr, \"Error while opening cud descriptor.\\n\");\n\t\treturn ERROR;\n\t}\n\n\twhile (fgets(buf, BUF_SIZE, cud) != NULL) {\n\t\ttoken = strtok(buf, \" \");\n\t\tStringToLower(token);\n\t\tif (strncmp(token, \"version\", 7) == 0) {\n\t\t\ttoken = strtok(NULL, \" \");\n\t\t\tif (token == NULL) {\n\t\t\t\tfprintf(stderr, \"Error while parsing update version.\");\n\t\t\t\treturn ERROR;\n\t\t\t}\n\n\t\t\ttoken = strtok(token, \".\");\n\t\t\tupdate_v->major = atoi(token);\n\t\t\ttoken = strtok(NULL, \".\");\n\t\t\tupdate_v->minor = atoi(token);\n\t\t\ttoken = strtok(NULL, \".\");\n\t\t\tupdate_v->revision = atoi(token);\n\t\t}\n\t}\n\n\tfclose(cud);\n\tremove(\"/tmp/update.cud\");\n\n\tif (stat(cup_pathname, &s_buf) != 0) {\n\t\tfprintf(stderr, \"Stat error!.\\n\");\n\t\treturn ERROR;\n\t}\n\n\tupdate_v->size = s_buf.st_size;\n\n\treturn SUCCESS;\n}\n\nint WUMSendCommitRequest(int acserver, int wtpId)\n{\n\twum_req_t msg;\n\twum_resp_t resp;\n\n\tWUM_INIT_REQ_MSG(msg, 0);\n\tmsg.cmd_msg = CONF_UPDATE_MSG;\n\tmsg.msg_elem = MSG_ELEMENT_TYPE_VENDOR_WUM;\n\tmsg.wtpId = wtpId;\n\tmsg.wum_type = WTP_COMMIT_UPDATE;\n\n\tif (WUMSendMessage(acserver, msg) != 0) {\n\t\tfprintf(stderr, \"Error while sending WUM message\");\n\t\treturn ERROR;\n\t}\n\n\tif (WUMReceiveMessage(acserver, &resp) != 0) {\n\t\tfprintf(stderr, \"Error while reading response message\");\n\t\treturn ERROR;\n\t}\n\n\tresp.wum_type = WUMPayloadRetrieve8(&resp);\n\tif (resp.wum_type != WTP_COMMIT_ACK) {\n\t\tfprintf(stderr, \"Received wrong response message!\");\n\t\treturn ERROR;\n\t}\n\n\treturn resp.resultCode;\n}\n\nint WUMSendCancelRequest(int acserver, int wtpId)\n{\n\twum_req_t msg;\n\twum_resp_t resp;\n\n\tWUM_INIT_REQ_MSG(msg, 0);\n\tmsg.cmd_msg = CONF_UPDATE_MSG;\n\tmsg.msg_elem = MSG_ELEMENT_TYPE_VENDOR_WUM;\n\tmsg.wtpId = wtpId;\n\tmsg.wum_type = WTP_CANCEL_UPDATE_REQUEST;\n\n\tif (WUMSendMessage(acserver, msg) != 0) {\n\t\tfprintf(stderr, \"Error while sending WUM message\");\n\t\treturn ERROR;\n\t}\n\n\tif (WUMReceiveMessage(acserver, &resp) != 0) {\n\t\tfprintf(stderr, \"Error while reading response message\");\n\t\treturn ERROR;\n\t}\n\n\tresp.wum_type = WUMPayloadRetrieve8(&resp);\n\tif (resp.wum_type != WTP_CANCEL_UPDATE_RESPONSE) {\n\t\tfprintf(stderr, \"Received wrong response message!\");\n\t\treturn ERROR;\n\t}\n\n\treturn resp.resultCode;\n}\n\nint WUMSendFragment(int acserver, int wtpId, void *buf, int size, int seq)\n{\n\twum_req_t msg;\n\twum_resp_t resp;\n\n\tWUM_INIT_REQ_MSG(msg, size + 2 * sizeof(int));\n\tmsg.cmd_msg = CONF_UPDATE_MSG;\n\tmsg.msg_elem = MSG_ELEMENT_TYPE_VENDOR_WUM;\n\tmsg.wtpId = wtpId;\n\tmsg.wum_type = WTP_CUP_FRAGMENT;\n\n\tWUMPayloadStore32(&msg, seq);\n\tWUMPayloadStore32(&msg, size);\n\tWUMPayloadStoreRawBytes(&msg, buf, size);\n\n\tif (WUMSendMessage(acserver, msg) != 0) {\n\t\tfprintf(stderr, \"Error while sending WUM message\");\n\t\treturn ERROR;\n\t}\n\n\tif (WUMReceiveMessage(acserver, &resp) != 0) {\n\t\tfprintf(stderr, \"Error while reading response message\");\n\t\treturn ERROR;\n\t}\n\n\tresp.wum_type = WUMPayloadRetrieve8(&resp);\n\tif (resp.wum_type != WTP_CUP_ACK) {\n\t\tfprintf(stderr, \"Received wrong response message!\");\n\t\treturn ERROR;\n\t}\n\n\tWUM_DESTROY_MSG(msg);\n\treturn resp.resultCode;\n}\n\nint WUMUpdate(int acserver, int wtpId, void *cup_buf, struct version_info update_v)\n{\n\tint i, left, toSend, sent;\n\n\tif (WUMSendUpdateRequest(acserver, wtpId, update_v)) {\n\t\tfprintf(stderr, \"Update request failed for WTP: %d\\n\", wtpId);\n\t\treturn ERROR;\n\t}\n\n\t/* Send update fragments */\n\tsent = 0;\n\tleft = update_v.size;\n\ttoSend = MIN(FRAGMENT_SIZE, left);\n\tfor (i = 0; left > 0; i++) {\n\t\tif (WUMSendFragment(acserver, wtpId, cup_buf + sent, toSend, i)) {\n\t\t\tfprintf(stderr, \"Error while sending fragment #%d\\n\", i);\n\t\t\treturn ERROR;\n\t\t}\n\t\tleft -= toSend;\n\t\tsent += toSend;\n\t\ttoSend = MIN(FRAGMENT_SIZE, left);\n\t}\n\n\tif (WUMSendCommitRequest(acserver, wtpId)) {\n\t\tfprintf(stderr, \"Update request failed for WTP: %d\\n\", wtpId);\n\t\treturn ERROR;\n\t}\n\n\treturn SUCCESS;\n}\n\nint WUMSendUpdateRequest(int acserver, int wtpId, struct version_info update_v)\n{\n\twum_req_t msg;\n\twum_resp_t resp;\n\n\tWUM_INIT_REQ_MSG(msg, 3 + sizeof(int));\n\tmsg.cmd_msg = CONF_UPDATE_MSG;\n\tmsg.msg_elem = MSG_ELEMENT_TYPE_VENDOR_WUM;\n\tmsg.wtpId = wtpId;\n\tmsg.wum_type = WTP_UPDATE_REQUEST;\n\n\tWUMPayloadStore8(&msg, update_v.major);\n\tWUMPayloadStore8(&msg, update_v.minor);\n\tWUMPayloadStore8(&msg, update_v.revision);\n\tWUMPayloadStore32(&msg, update_v.size);\n\n\tif (WUMSendMessage(acserver, msg) != 0) {\n\t\tfprintf(stderr, \"Error while sending WUM message\");\n\t\treturn ERROR;\n\t}\n\n\tif (WUMReceiveMessage(acserver, &resp) != 0) {\n\t\tfprintf(stderr, \"Error while reading response message\");\n\t\treturn ERROR;\n\t}\n\n\tWUM_DESTROY_MSG(msg)\n\t    return resp.resultCode;\n\n}\n\nint WUMSendMessage(int acserver, wum_req_t msg)\n{\n\t/* Fix byte order issues */\n\tmsg.wtpId = htonl(msg.wtpId);\n\n\tif (Writen(acserver, &msg, 7) != 7) {\n\t\tfprintf(stderr, \"Error while sending CONF_UPDATE_MSG message.\\n\");\n\t\treturn ERROR;\n\t}\n\n\tif (msg.payload_len > 0) {\n\t\tif (Writen(acserver, msg.payload, msg.payload_len) != msg.payload_len) {\n\t\t\tfprintf(stderr, \"Error while sending CONF_UPDATE_MSG message.\\n\");\n\t\t\treturn ERROR;\n\t\t}\n\t}\n\n\treturn SUCCESS;\n}\n\nint WUMReceiveMessage(int acserver, wum_resp_t * msg)\n{\n\tint len;\n\n\tmsg->offset = 0;\n\n\tif (Read32(acserver, &(msg->wtpId)) != 4) {\n\t\tfprintf(stderr, \"Error while reading wtpId.\\n\");\n\t\treturn ERROR;\n\t}\n\n\tif (Read32(acserver, &(msg->resultCode)) != 4) {\n\t\tfprintf(stderr, \"Error while reading result code.\\n\");\n\t\treturn ERROR;\n\t}\n\n\tif (Read32(acserver, &(msg->payload_len)) != 4) {\n\t\tfprintf(stderr, \"Error while reading payload length.\\n\");\n\t\treturn ERROR;\n\t}\n\n\tif (msg->payload_len > 0) {\n\n\t\tmsg->payload = malloc(msg->payload_len);\n\n\t\tif (Readn(acserver, msg->payload, msg->payload_len) != msg->payload_len) {\n\t\t\tfprintf(stderr, \"Error while reading payload.\\n\");\n\t\t\treturn ERROR;\n\t\t}\n\t}\n\n\treturn SUCCESS;\n}\n\nchar WUMPayloadRetrieve8(wum_resp_t * resp)\n{\n\treturn resp->payload[resp->offset++];\n}\n\nvoid WUMPayloadStore8(wum_req_t * req, char c)\n{\n\treq->payload[req->payload_len++] = c;\n}\n\nvoid WUMPayloadStore32(wum_req_t * req, int i)\n{\n\ti = htonl(i);\n\tmemcpy(req->payload + req->payload_len, &i, 4);\n\treq->payload_len += 4;\n}\n\nvoid WUMPayloadStoreRawBytes(wum_req_t * req, void *buf, int size)\n{\n\tmemcpy(req->payload + req->payload_len, buf, size);\n\treq->payload_len += size;\n}\n\nint /* Read \"n\" bytes from a descriptor. */ readn(int fd, void *vptr, size_t n)\n{\n\tsize_t nleft;\n\tssize_t nread;\n\tchar *ptr;\n\n\tptr = vptr;\n\tnleft = n;\n\twhile (nleft > 0) {\n\t\tif ((nread = recv(fd, ptr, nleft, 0)) < 0) {\n\t\t\tif (errno == EINTR)\n\t\t\t\tnread = 0;\t/* and call read() again */\n\t\t\telse\n\t\t\t\treturn (-1);\n\t\t} else if (nread == 0)\n\t\t\tbreak;\t/* EOF */\n\n\t\tnleft -= nread;\n\t\tptr += nread;\n\t}\n\treturn (n - nleft);\t/* return >= 0 */\n}\n\nint Readn(int fd, void *ptr, size_t nbytes)\n{\n\tint n;\n\n\tif ((n = readn(fd, ptr, nbytes)) < 0)\n\t\tperror(\"readn error\");\n\treturn (n);\n}\n\nint /* Write \"n\" bytes to a descriptor. */ writen(int fd, const void *vptr, size_t n)\n{\n\tsize_t nleft;\n\tssize_t nwritten;\n\tconst char *ptr;\n\n\tptr = vptr;\n\tnleft = n;\n\twhile (nleft > 0) {\n\t\tif ((nwritten = send(fd, ptr, nleft, 0)) <= 0) {\n\t\t\tif (errno == EINTR)\n\t\t\t\tnwritten = 0;\t/* and call write() again */\n\t\t\telse\n\t\t\t\treturn (-1);\t/* error */\n\t\t}\n\n\t\tnleft -= nwritten;\n\t\tptr += nwritten;\n\t}\n\treturn (n);\n}\n\nint Writen(int fd, void *ptr, size_t nbytes)\n{\n\tint n;\n\twhile ((n = writen(fd, ptr, nbytes)) < 0)\n\t\tperror(\"writen error\");\n\treturn n;\n}\n\nint Read32(int fd, int *ptr)\n{\n\tint ret;\n\n\tret = Readn(fd, ptr, 4);\n\n\t*ptr = ntohl(*ptr);\n\n\treturn ret;\n}\n\nint Write32(int fd, void *ptr)\n{\n}\n"
  },
  {
    "path": "wum/wumLib.h",
    "content": "\n#include <stdio.h>\n\n#define QUIT_MSG 0\n#define LIST_MSG 1\n#define CONF_UPDATE_MSG 2\n\n#define MSG_ELEMENT_TYPE_VENDOR_WUM 3\n\n#define WTP_VERSION_REQUEST     1\n#define WTP_VERSION_RESPONSE    2\n\n#define WTP_UPDATE_REQUEST      3\n#define WTP_UPDATE_RESPONSE     4\n\n#define WTP_CUP_FRAGMENT        5\n#define WTP_CUP_ACK             6\n\n#define WTP_COMMIT_UPDATE       7\n#define WTP_COMMIT_ACK          8\n\n#define WTP_CANCEL_UPDATE_REQUEST       9\n#define WTP_CANCEL_UPDATE_RESPONSE       10\n\n#define SUCCESS 0\n#define ERROR   1\n\n#define FRAGMENT_SIZE 4000\n\nstruct WTPInfo {\n\tint wtpId;\n\tchar *name;\n};\n\nstruct version_info {\n\tchar major;\n\tchar minor;\n\tchar revision;\n\tint size;\n};\n\nint ACServerConnect(char *address, int port);\nvoid ACServerDisconnect(int acserver);\nstruct WTPInfo *ACServerWTPList(int acserver, int *nWTPs);\nvoid freeWTPList(struct WTPInfo *wtpList, int nWTPs);\n\nint WUMGetWTPVersion(int acserver, int wtpId, struct version_info *);\nint WUMReadCupVersion(char *cup_pathname, struct version_info *update_v);\nint WUMUpdate(int acserver, int wtpId, void *cup_buf, struct version_info update_v);\nint WUMSendCancelRequest(int acserver, int wtpId);\n"
  }
]