"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.1.300/src/server/core/accesspoint.cpp" (7 Jan 2020, 16304 Bytes) of package /linux/misc/netxms-3.1.300.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "accesspoint.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.0.2357_vs_3.1.241.

    1 /*
    2 ** NetXMS - Network Management System
    3 ** Copyright (C) 2003-2019 Victor Kirhenshtein
    4 **
    5 ** This program is free software; you can redistribute it and/or modify
    6 ** it under the terms of the GNU General Public License as published by
    7 ** the Free Software Foundation; either version 2 of the License, or
    8 ** (at your option) any later version.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13 ** GNU General Public License for more details.
   14 **
   15 ** You should have received a copy of the GNU General Public License
   16 ** along with this program; if not, write to the Free Software
   17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18 **
   19 ** File: accesspoint.cpp
   20 **/
   21 
   22 #include "nxcore.h"
   23 
   24 /**
   25  * Default constructor
   26  */
   27 AccessPoint::AccessPoint() : super(), m_macAddr(MacAddress::ZERO)
   28 {
   29     m_nodeId = 0;
   30    m_index = 0;
   31     m_vendor = NULL;
   32     m_model = NULL;
   33     m_serialNumber = NULL;
   34     m_radioInterfaces = NULL;
   35     m_apState = AP_ADOPTED;
   36    m_prevState = m_apState;
   37 }
   38 
   39 /**
   40  * Constructor for creating new access point object
   41  */
   42 AccessPoint::AccessPoint(const TCHAR *name, UINT32 index, const BYTE *macAddr) : super(name), m_macAddr(macAddr, MAC_ADDR_LENGTH)
   43 {
   44     m_nodeId = 0;
   45    m_index = index;
   46     m_vendor = NULL;
   47     m_model = NULL;
   48     m_serialNumber = NULL;
   49     m_radioInterfaces = NULL;
   50     m_apState = AP_ADOPTED;
   51    m_prevState = m_apState;
   52     m_isHidden = true;
   53 }
   54 
   55 /**
   56  * Destructor
   57  */
   58 AccessPoint::~AccessPoint()
   59 {
   60     MemFree(m_vendor);
   61     MemFree(m_model);
   62     MemFree(m_serialNumber);
   63     delete m_radioInterfaces;
   64 }
   65 
   66 /**
   67  * Create object from database data
   68  */
   69 bool AccessPoint::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId)
   70 {
   71    m_id = dwId;
   72 
   73    if (!loadCommonProperties(hdb))
   74    {
   75       DbgPrintf(2, _T("Cannot load common properties for access point object %d"), dwId);
   76       return false;
   77    }
   78 
   79     TCHAR query[256];
   80     _sntprintf(query, 256, _T("SELECT mac_address,vendor,model,serial_number,node_id,ap_state,ap_index FROM access_points WHERE id=%d"), (int)m_id);
   81     DB_RESULT hResult = DBSelect(hdb, query);
   82     if (hResult == NULL)
   83         return false;
   84 
   85     m_macAddr = DBGetFieldMacAddr(hResult, 0, 0);
   86     m_vendor = DBGetField(hResult, 0, 1, NULL, 0);
   87     m_model = DBGetField(hResult, 0, 2, NULL, 0);
   88     m_serialNumber = DBGetField(hResult, 0, 3, NULL, 0);
   89     m_nodeId = DBGetFieldULong(hResult, 0, 4);
   90     m_apState = (AccessPointState)DBGetFieldLong(hResult, 0, 5);
   91    m_prevState = (m_apState != AP_DOWN) ? m_apState : AP_ADOPTED;
   92    m_index = DBGetFieldULong(hResult, 0, 6);
   93     DBFreeResult(hResult);
   94 
   95    // Load DCI and access list
   96    loadACLFromDB(hdb);
   97    loadItemsFromDB(hdb);
   98    for(int i = 0; i < m_dcObjects->size(); i++)
   99       if (!m_dcObjects->get(i)->loadThresholdsFromDB(hdb))
  100          return false;
  101 
  102    // Link access point to node
  103     bool success = false;
  104    if (!m_isDeleted)
  105    {
  106       NetObj *object = FindObjectById(m_nodeId, OBJECT_NODE);
  107       if (object == NULL)
  108       {
  109          nxlog_write(NXLOG_ERROR, _T("Inconsistent database: access point %s [%u] linked to non-existent node [%u]"), m_name, m_id, m_nodeId);
  110       }
  111       else
  112       {
  113          object->addChild(this);
  114          addParent(object);
  115          success = true;
  116       }
  117    }
  118    else
  119    {
  120       success = true;
  121    }
  122 
  123    return success;
  124 }
  125 
  126 /**
  127  * Save object to database
  128  */
  129 bool AccessPoint::saveToDatabase(DB_HANDLE hdb)
  130 {
  131    // Lock object's access
  132    lockProperties();
  133 
  134    bool success = saveCommonProperties(hdb);
  135 
  136    if (success && (m_modified & MODIFY_OTHER))
  137    {
  138       DB_STATEMENT hStmt;
  139       if (IsDatabaseRecordExist(hdb, _T("access_points"), _T("id"), m_id))
  140          hStmt = DBPrepare(hdb, _T("UPDATE access_points SET mac_address=?,vendor=?,model=?,serial_number=?,node_id=?,ap_state=?,ap_index=? WHERE id=?"));
  141       else
  142          hStmt = DBPrepare(hdb, _T("INSERT INTO access_points (mac_address,vendor,model,serial_number,node_id,ap_state,ap_index,id) VALUES (?,?,?,?,?,?,?,?)"));
  143       if (hStmt != NULL)
  144       {
  145          DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_macAddr);
  146          DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_vendor, DB_BIND_STATIC);
  147          DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, m_model, DB_BIND_STATIC);
  148          DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, m_serialNumber, DB_BIND_STATIC);
  149          DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, m_nodeId);
  150          DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (INT32)m_apState);
  151          DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_index);
  152          DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_id);
  153 
  154          success = DBExecute(hStmt);
  155 
  156          DBFreeStatement(hStmt);
  157       }
  158       else
  159       {
  160          success = false;
  161       }
  162    }
  163 
  164    // Save data collection items
  165    if (success && (m_modified & MODIFY_DATA_COLLECTION))
  166    {
  167         lockDciAccess(false);
  168       for(int i = 0; i < m_dcObjects->size(); i++)
  169          m_dcObjects->get(i)->saveToDatabase(hdb);
  170         unlockDciAccess();
  171    }
  172 
  173    // Save access list
  174    if (success)
  175       success = saveACLToDB(hdb);
  176    unlockProperties();
  177 
  178    return success;
  179 }
  180 
  181 /**
  182  * Delete object from database
  183  */
  184 bool AccessPoint::deleteFromDatabase(DB_HANDLE hdb)
  185 {
  186    bool success = super::deleteFromDatabase(hdb);
  187    if (success)
  188       success = executeQueryOnObject(hdb, _T("DELETE FROM access_points WHERE id=?"));
  189    return success;
  190 }
  191 
  192 /**
  193  * Create CSCP message with object's data
  194  */
  195 void AccessPoint::fillMessageInternal(NXCPMessage *msg, UINT32 userId)
  196 {
  197    super::fillMessageInternal(msg, userId);
  198    msg->setField(VID_IP_ADDRESS, m_ipAddress);
  199     msg->setField(VID_NODE_ID, m_nodeId);
  200     msg->setField(VID_MAC_ADDR, m_macAddr);
  201     msg->setField(VID_VENDOR, CHECK_NULL_EX(m_vendor));
  202     msg->setField(VID_MODEL, CHECK_NULL_EX(m_model));
  203     msg->setField(VID_SERIAL_NUMBER, CHECK_NULL_EX(m_serialNumber));
  204    msg->setField(VID_STATE, (UINT16)m_apState);
  205    msg->setField(VID_AP_INDEX, m_index);
  206 
  207    if (m_radioInterfaces != NULL)
  208    {
  209       msg->setField(VID_RADIO_COUNT, (WORD)m_radioInterfaces->size());
  210       UINT32 varId = VID_RADIO_LIST_BASE;
  211       for(int i = 0; i < m_radioInterfaces->size(); i++)
  212       {
  213          RadioInterfaceInfo *rif = m_radioInterfaces->get(i);
  214          msg->setField(varId++, (UINT32)rif->index);
  215          msg->setField(varId++, rif->name);
  216          msg->setField(varId++, rif->macAddr, MAC_ADDR_LENGTH);
  217          msg->setField(varId++, rif->channel);
  218          msg->setField(varId++, (UINT32)rif->powerDBm);
  219          msg->setField(varId++, (UINT32)rif->powerMW);
  220          varId += 4;
  221       }
  222    }
  223    else
  224    {
  225       msg->setField(VID_RADIO_COUNT, (WORD)0);
  226    }
  227 }
  228 
  229 /**
  230  * Modify object from message
  231  */
  232 UINT32 AccessPoint::modifyFromMessageInternal(NXCPMessage *request)
  233 {
  234    if (request->isFieldExist(VID_FLAGS))
  235    {
  236       UINT32 mask = request->isFieldExist(VID_FLAGS_MASK) ? request->getFieldAsUInt32(VID_FLAGS_MASK) : 0xFFFFFFFF;
  237       m_flags &= ~mask;
  238       m_flags |= request->getFieldAsUInt32(VID_FLAGS) & mask;
  239    }
  240    return super::modifyFromMessageInternal(request);
  241 }
  242 
  243 /**
  244  * Attach access point to node
  245  */
  246 void AccessPoint::attachToNode(UINT32 nodeId)
  247 {
  248     if (m_nodeId == nodeId)
  249         return;
  250 
  251     if (m_nodeId != 0)
  252     {
  253         Node *currNode = (Node *)FindObjectById(m_nodeId, OBJECT_NODE);
  254         if (currNode != NULL)
  255         {
  256             currNode->deleteChild(this);
  257             deleteParent(currNode);
  258         }
  259     }
  260 
  261     Node *newNode = (Node *)FindObjectById(nodeId, OBJECT_NODE);
  262     if (newNode != NULL)
  263     {
  264         newNode->addChild(this);
  265         addParent(newNode);
  266     }
  267 
  268     lockProperties();
  269     m_nodeId = nodeId;
  270     setModified(MODIFY_OTHER);
  271     unlockProperties();
  272 }
  273 
  274 /**
  275  * Update radio interfaces information
  276  */
  277 void AccessPoint::updateRadioInterfaces(const ObjectArray<RadioInterfaceInfo> *ri)
  278 {
  279     lockProperties();
  280     if (m_radioInterfaces == NULL)
  281         m_radioInterfaces = new ObjectArray<RadioInterfaceInfo>(ri->size(), 4, true);
  282     m_radioInterfaces->clear();
  283     for(int i = 0; i < ri->size(); i++)
  284     {
  285         RadioInterfaceInfo *info = new RadioInterfaceInfo;
  286         memcpy(info, ri->get(i), sizeof(RadioInterfaceInfo));
  287         m_radioInterfaces->add(info);
  288     }
  289     unlockProperties();
  290 }
  291 
  292 /**
  293  * Check if given radio interface index (radio ID) is on this access point
  294  */
  295 bool AccessPoint::isMyRadio(int rfIndex)
  296 {
  297     bool result = false;
  298     lockProperties();
  299     if (m_radioInterfaces != NULL)
  300     {
  301         for(int i = 0; i < m_radioInterfaces->size(); i++)
  302         {
  303             if (m_radioInterfaces->get(i)->index == rfIndex)
  304             {
  305                 result = true;
  306                 break;
  307             }
  308         }
  309     }
  310     unlockProperties();
  311     return result;
  312 }
  313 
  314 /**
  315  * Check if given radio MAC address (BSSID) is on this access point
  316  */
  317 bool AccessPoint::isMyRadio(const BYTE *macAddr)
  318 {
  319     bool result = false;
  320     lockProperties();
  321     if (m_radioInterfaces != NULL)
  322     {
  323         for(int i = 0; i < m_radioInterfaces->size(); i++)
  324         {
  325          if (!memcmp(m_radioInterfaces->get(i)->macAddr, macAddr, MAC_ADDR_LENGTH))
  326             {
  327                 result = true;
  328                 break;
  329             }
  330         }
  331     }
  332     unlockProperties();
  333     return result;
  334 }
  335 
  336 /**
  337  * Get radio name
  338  */
  339 void AccessPoint::getRadioName(int rfIndex, TCHAR *buffer, size_t bufSize)
  340 {
  341     buffer[0] = 0;
  342     lockProperties();
  343     if (m_radioInterfaces != NULL)
  344     {
  345         for(int i = 0; i < m_radioInterfaces->size(); i++)
  346         {
  347             if (m_radioInterfaces->get(i)->index == rfIndex)
  348             {
  349                 _tcslcpy(buffer, m_radioInterfaces->get(i)->name, bufSize);
  350                 break;
  351             }
  352         }
  353     }
  354     unlockProperties();
  355 }
  356 
  357 /**
  358  * Get access point's parent node
  359  */
  360 Node *AccessPoint::getParentNode()
  361 {
  362    return static_cast<Node*>(FindObjectById(m_nodeId, OBJECT_NODE));
  363 }
  364 
  365 /**
  366  * Update access point information
  367  */
  368 void AccessPoint::updateInfo(const TCHAR *vendor, const TCHAR *model, const TCHAR *serialNumber)
  369 {
  370     lockProperties();
  371 
  372     MemFree(m_vendor);
  373     m_vendor = MemCopyString(vendor);
  374 
  375     MemFree(m_model);
  376     m_model = MemCopyString(model);
  377 
  378     MemFree(m_serialNumber);
  379     m_serialNumber = MemCopyString(serialNumber);
  380 
  381     setModified(MODIFY_OTHER);
  382     unlockProperties();
  383 }
  384 
  385 /**
  386  * Update access point state
  387  */
  388 void AccessPoint::updateState(AccessPointState state)
  389 {
  390    if (state == m_apState)
  391       return;
  392 
  393     lockProperties();
  394    if (state == AP_DOWN)
  395       m_prevState = m_apState;
  396    m_apState = state;
  397    if (m_status != STATUS_UNMANAGED)
  398    {
  399       switch(state)
  400       {
  401          case AP_ADOPTED:
  402             m_status = STATUS_NORMAL;
  403             break;
  404          case AP_UNADOPTED:
  405             m_status = STATUS_MAJOR;
  406             break;
  407          case AP_DOWN:
  408             m_status = STATUS_CRITICAL;
  409             break;
  410          default:
  411             m_status = STATUS_UNKNOWN;
  412             break;
  413       }
  414    }
  415    setModified(MODIFY_OTHER);
  416     unlockProperties();
  417 
  418    if ((state == AP_ADOPTED) || (state == AP_UNADOPTED) || (state == AP_DOWN))
  419    {
  420       static const TCHAR *names[] = { _T("id"), _T("name"), _T("macAddr"), _T("ipAddr"), _T("vendor"), _T("model"), _T("serialNumber") };
  421       PostSystemEventWithNames((state == AP_ADOPTED) ? EVENT_AP_ADOPTED : ((state == AP_UNADOPTED) ? EVENT_AP_UNADOPTED : EVENT_AP_DOWN),
  422          m_nodeId, "isHAsss", names,
  423          m_id, m_name, &m_macAddr, &m_ipAddress,
  424          CHECK_NULL_EX(m_vendor), CHECK_NULL_EX(m_model), CHECK_NULL_EX(m_serialNumber));
  425    }
  426 }
  427 
  428 /**
  429  * Do status poll
  430  */
  431 void AccessPoint::statusPollFromController(ClientSession *session, UINT32 rqId, ObjectQueue<Event> *eventQueue,
  432          Node *controller, SNMP_Transport *snmpTransport)
  433 {
  434    m_pollRequestor = session;
  435 
  436    sendPollerMsg(rqId, _T("   Starting status poll on access point %s\r\n"), m_name);
  437    sendPollerMsg(rqId, _T("      Current access point status is %s\r\n"), GetStatusAsText(m_status, true));
  438 
  439    AccessPointState state = controller->getAccessPointState(this, snmpTransport, m_radioInterfaces);
  440    if ((state == AP_UNKNOWN) && m_ipAddress.isValid())
  441    {
  442       DbgPrintf(6, _T("AccessPoint::statusPoll(%s [%d]): unable to get AP state from driver"), m_name, m_id);
  443       sendPollerMsg(rqId, POLLER_WARNING _T("      Unable to get AP state from controller\r\n"));
  444 
  445         UINT32 icmpProxy = 0;
  446 
  447       if (IsZoningEnabled() && (controller->getZoneUIN() != 0))
  448         {
  449             Zone *zone = FindZoneByUIN(controller->getZoneUIN());
  450             if (zone != NULL)
  451             {
  452                 icmpProxy = zone->getProxyNodeId(this);
  453             }
  454         }
  455 
  456         if (icmpProxy != 0)
  457         {
  458             sendPollerMsg(rqId, _T("      Starting ICMP ping via proxy\r\n"));
  459             DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): ping via proxy [%u]"), m_id, m_name, icmpProxy);
  460             Node *proxyNode = (Node *)g_idxNodeById.get(icmpProxy);
  461             if ((proxyNode != NULL) && proxyNode->isNativeAgent() && !proxyNode->isDown())
  462             {
  463                 DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): proxy node found: %s"), m_id, m_name, proxyNode->getName());
  464                 AgentConnection *conn = proxyNode->createAgentConnection();
  465                 if (conn != NULL)
  466                 {
  467                     TCHAR parameter[64], buffer[64];
  468 
  469                     _sntprintf(parameter, 64, _T("Icmp.Ping(%s)"), m_ipAddress.toString(buffer));
  470                     if (conn->getParameter(parameter, 64, buffer) == ERR_SUCCESS)
  471                     {
  472                         DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): proxy response: \"%s\""), m_id, m_name, buffer);
  473                         TCHAR *eptr;
  474                         long value = _tcstol(buffer, &eptr, 10);
  475                         if ((*eptr == 0) && (value >= 0))
  476                         {
  477                      if (value < 10000)
  478                      {
  479                         sendPollerMsg(rqId, POLLER_ERROR _T("      responded to ICMP ping\r\n"));
  480                         if (m_apState == AP_DOWN)
  481                            state = m_prevState;  /* FIXME: get actual AP state here */
  482                      }
  483                      else
  484                      {
  485                         sendPollerMsg(rqId, POLLER_ERROR _T("      no response to ICMP ping\r\n"));
  486                         state = AP_DOWN;
  487                      }
  488                         }
  489                     }
  490                     conn->disconnect();
  491                     conn->decRefCount();
  492                 }
  493                 else
  494                 {
  495                     DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): cannot connect to agent on proxy node"), m_id, m_name);
  496                     sendPollerMsg(rqId, POLLER_ERROR _T("      Unable to establish connection with proxy node\r\n"));
  497                 }
  498             }
  499             else
  500             {
  501                 DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): proxy node not available"), m_id, m_name);
  502                 sendPollerMsg(rqId, POLLER_ERROR _T("      ICMP proxy not available\r\n"));
  503             }
  504         }
  505         else    // not using ICMP proxy
  506         {
  507          TCHAR buffer[64];
  508             sendPollerMsg(rqId, _T("      Starting ICMP ping\r\n"));
  509             DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): calling IcmpPing(%s,3,%d,NULL,%d)"), m_id, m_name, m_ipAddress.toString(buffer), g_icmpPingTimeout, g_icmpPingSize);
  510             UINT32 responseTime;
  511             UINT32 dwPingStatus = IcmpPing(m_ipAddress, 3, g_icmpPingTimeout, &responseTime, g_icmpPingSize, false);
  512             if (dwPingStatus == ICMP_SUCCESS)
  513          {
  514                 sendPollerMsg(rqId, POLLER_ERROR _T("      responded to ICMP ping\r\n"));
  515             if (m_apState == AP_DOWN)
  516                state = m_prevState;  /* FIXME: get actual AP state here */
  517          }
  518          else
  519             {
  520                 sendPollerMsg(rqId, POLLER_ERROR _T("      no response to ICMP ping\r\n"));
  521             state = AP_DOWN;
  522             }
  523             DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): ping result %d, state=%d"), m_id, m_name, dwPingStatus, state);
  524         }
  525    }
  526 
  527    updateState(state);
  528 
  529    sendPollerMsg(rqId, _T("      Access point status after poll is %s\r\n"), GetStatusAsText(m_status, true));
  530     sendPollerMsg(rqId, _T("   Finished status poll on access point %s\r\n"), m_name);
  531 }
  532 
  533 /**
  534  * Create NXSL object for this object
  535  */
  536 NXSL_Value *AccessPoint::createNXSLObject(NXSL_VM *vm)
  537 {
  538    return vm->createValue(new NXSL_Object(vm, &g_nxslAccessPointClass, this));
  539 }
  540 
  541 /**
  542  * Serialize object to JSON
  543  */
  544 json_t *AccessPoint::toJson()
  545 {
  546    json_t *root = super::toJson();
  547 
  548    lockProperties();
  549    json_object_set_new(root, "index", json_integer(m_index));
  550    json_object_set_new(root, "ipAddress", m_ipAddress.toJson());
  551    json_object_set_new(root, "nodeId", json_integer(m_nodeId));
  552    TCHAR macAddrText[64];
  553    json_object_set_new(root, "macAddr", json_string_t(m_macAddr.toString(macAddrText)));
  554    json_object_set_new(root, "vendor", json_string_t(m_vendor));
  555    json_object_set_new(root, "model", json_string_t(m_model));
  556    json_object_set_new(root, "serialNumber", json_string_t(m_serialNumber));
  557    json_object_set_new(root, "radioInterfaces", json_object_array(m_radioInterfaces));
  558    json_object_set_new(root, "state", json_integer(m_apState));
  559    json_object_set_new(root, "prevState", json_integer(m_prevState));
  560    unlockProperties();
  561 
  562    return root;
  563 }