From f826af0af5f41bd667aa4bcbe5c168dbf1b52008 Mon Sep 17 00:00:00 2001 From: Amitabha Sen Date: Tue, 10 Oct 2023 01:40:44 -0700 Subject: [PATCH 1/2] Added initial support for mab and hostapdmgr --- hostapdmgr/hostapdmgr.cpp | 1693 ++++++++++++++++++++++++++++++++ hostapdmgr/hostapdmgr.h | 142 +++ hostapdmgr/hostapdmgr_main.cpp | 135 +++ mabmgr/mabmgr.cpp | 1051 ++++++++++++++++++++ mabmgr/mabmgr.h | 135 +++ mabmgr/mabmgr_main.cpp | 110 +++ 6 files changed, 3266 insertions(+) create mode 100644 hostapdmgr/hostapdmgr.cpp create mode 100644 hostapdmgr/hostapdmgr.h create mode 100644 hostapdmgr/hostapdmgr_main.cpp create mode 100644 mabmgr/mabmgr.cpp create mode 100644 mabmgr/mabmgr.h create mode 100644 mabmgr/mabmgr_main.cpp diff --git a/hostapdmgr/hostapdmgr.cpp b/hostapdmgr/hostapdmgr.cpp new file mode 100644 index 0000000..a05f912 --- /dev/null +++ b/hostapdmgr/hostapdmgr.cpp @@ -0,0 +1,1693 @@ +/* + * Copyright 2019 Broadcom Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "hostapdmgr.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wpa_ctrl.h" +#include "tokenize.h" + +#define TEAM_DRV_NAME "team" +#define HOSTAPD_CMD_BUFFSZ 2048 + +const string MGMT_PREFIX = "eth"; +const string INTFS_PREFIX = "E"; +const string LAG_PREFIX = "PortChannel"; + +const string HOSTAPD_PID_FILE = "/etc/hostapd/hostapdPid"; +const string HOSTAPD_SERVER_TIMEOUT = "serverTimeout"; +const string HOSTAPD_QUIET_PERIOD = "quietPeriod"; + +HostapdMgr *hostapd; + +DEBUGSH_CLI(HostapdMgrRadiusStats, + "show system internal hostapdmgr radius-stats ETHERNETNAME", + SHOW_COMMAND, + SYSTEM_DEBUG_COMMAND, + INTERNAL_COMMAND, + "HostapdMgr related commands", + "Radius stats", + "Interface") +{ + string intf = ""; + + if (args.size() == 0) + { + return; + } + + intf = args[0]; + + hostapd->showDebugInfo(this, intf); +} + +HostapdMgr::HostapdMgr(DBConnector *configDb, DBConnector *appDb) : + m_confHostapdPortTbl(configDb, CFG_PAC_PORT_CONFIG_TABLE), + m_confHostapdGlobalTbl(configDb, CFG_PAC_HOSTAPD_GLOBAL_CONFIG_TABLE), + m_confRadiusServerTable(configDb, "RADIUS_SERVER"), + m_confRadiusGlobalTable(configDb, "RADIUS"), + m_mgmtIntfTbl(appDb, "MGMT_INTF_TABLE"), + m_IntfTbl(configDb, CFG_INTF_TABLE_NAME), + m_VlanIntfTbl(configDb, CFG_VLAN_INTF_TABLE_NAME), + m_LoIntfTbl(configDb, CFG_LOOPBACK_INTERFACE_TABLE_NAME), + m_PoIntfTbl(configDb, CFG_LAG_INTF_TABLE_NAME) + +{ + Logger::linkToDbNative("hostapdmgr"); + memset(&m_glbl_info, 0, sizeof(m_glbl_info)); + active_intf_cnt = 0; + start_hostapd = false; + stop_hostapd = false; + + hostapd = this; + SWSS_LOG_DEBUG("Installing HostapdMgr commands"); + DebugShCmd::install(new HostapdMgrRadiusStats()); +} + +void HostapdMgr::showDebugInfo(DebugShCmd *cmd, string intf) +{ + string cmdstr = "hostapd_cli -i " + intf + " mib"; + array buffer; + FILE* pipe = popen(cmdstr.c_str(), "r"); + string output; + + if (pipe) { + + DEBUGSH_OUT(cmd, "Dumping Hostapdmgr radius stats\n\n"); + DEBUGSH_OUT(cmd, "==============================================\n"); + + while (!feof(pipe)) { + if (fgets(buffer.data(), HOSTAPD_CMD_BUFFSZ, pipe) != NULL) { + output.clear(); + output += buffer.data(); + + DEBUGSH_OUT(cmd, "%s", output.c_str()); + } + } + + DEBUGSH_OUT(cmd, "\n==============================================\n\n"); + + if (0 != pclose(pipe)) { + DEBUGSH_OUT(cmd, "dot1x not enabled or HOSTAPD not running.\n"); + } + } + else + { + DEBUGSH_OUT(cmd, "dot1x not enabled or HOSTAPD not running.\n"); + } +} + +string HostapdMgr::getStdIfFormat(string key) +{ + if((key.find("E") == string::npos) || (key.length() > 8)) + { + return key; + } + string key1(""); + key1 = "Eth" + key.substr(1,1) + '/' + key.substr(3); + return key1; +} + +vector HostapdMgr::getSelectables() { + vector selectables{ &m_confHostapdPortTbl, &m_confHostapdGlobalTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable, + &m_mgmtIntfTbl, &m_IntfTbl, &m_VlanIntfTbl, &m_PoIntfTbl, &m_LoIntfTbl }; + return selectables; +} + +bool HostapdMgr::processDbEvent(Selectable *tbl) { + + SWSS_LOG_ENTER(); + SWSS_LOG_DEBUG("Received a HOSTAPD Database event"); + + //check the source table and accordingly invoke the appropriate handlers + + if (tbl == ((Selectable *) & m_confHostapdPortTbl)) { + return processHostapdConfigPortTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_confHostapdGlobalTbl)) { + return processHostapdConfigGlobalTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_confRadiusServerTable)) { + return processRadiusServerTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_confRadiusGlobalTable)) { + return processRadiusGlobalTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_mgmtIntfTbl)) { + return processMgmtIntfTblEvent(tbl); + } + + if ((tbl == ((Selectable *) & m_IntfTbl)) || + (tbl == ((Selectable *) & m_VlanIntfTbl)) || + (tbl == ((Selectable *) & m_LoIntfTbl)) || + (tbl == ((Selectable *) & m_PoIntfTbl))) { + return processIntfTblEvent(tbl); + } + + SWSS_LOG_DEBUG("Received event UNKNOWN to HOSTAPD, ignoring "); + return false; +} + +//Process the config db table events + +bool HostapdMgr::processHostapdConfigPortTblEvent(Selectable *tbl) +{ + + SWSS_LOG_ENTER(); + SWSS_LOG_DEBUG("Received an table config event on PAC_PORT_CONFIG_TABLE table"); + + deque entries; + m_confHostapdPortTbl.pops(entries); + + SWSS_LOG_NOTICE("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + // Check through all the data + for (auto entry : entries) + { + string key = kfvKey(entry); + string val = kfvOp(entry); + + SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); + + if (m_intf_info.find(key) == m_intf_info.end()) + { + SWSS_LOG_NOTICE("Cannot find interface %s in local db. Adding it now", key.c_str()); + hostapd_intf_info_t intf; + intf.control_mode = "force-authorized"; + intf.capabilities = "none"; + intf.quiet_period = PAC_QUIET_PERIOD_DEF; + intf.server_timeout = PAC_SERVER_TIMEOUT_DEF; + intf.server_timeout_modified = false; + intf.quiet_period_modified = false; + intf.admin_status = 0; + intf.link_status = 0; + intf.config_created = false; + setPort(key, intf); + } + + SWSS_LOG_NOTICE("intf-- %s capabilities %s ctrl_mode %s admin_status %d link_status %d, global_auth %d", + key.c_str(), m_intf_info[key].capabilities.c_str(), + m_intf_info[key].control_mode.c_str(),m_intf_info[key].admin_status, + m_intf_info[key].link_status, m_glbl_info.enable_auth); + + if (m_radius_info.radius_auth_server_list.size()) + { + SWSS_LOG_NOTICE("m_radius_info.radius_auth_server_list.size() is non-zero "); + } + if (val == SET_COMMAND) + { + vector new_interfaces; + vector del_interfaces; + + // Look at the data that is sent for this key + for (auto i : kfvFieldsValues(entry)) + { + string a = fvField(i); + string b = fvValue(i); + + SWSS_LOG_NOTICE("Received %s as field and %s as value", a.c_str(), b.c_str()); + + if ((a == "port_pae_role") && (m_intf_info[key].capabilities != b)) + { + if (b == "authenticator") + { + // pae role authenticator + if ((m_glbl_info.enable_auth) && (m_intf_info[key].link_status) && (!m_intf_info[key].config_created) && + (m_intf_info[key].control_mode == "auto") && (m_radiusServerInUse != "")) + { + /* create config file */ + createConfFile(key); + + /* update interfaces list */ + new_interfaces.push_back(key); + } + } + else + { + // pae role none + if (m_intf_info[key].config_created) + { + /* delete config file */ + deleteConfFile(key); + + /* update interfaces list */ + del_interfaces.push_back(key); + } + } + m_intf_info[key].capabilities = b; + } + else if ((a == "port_control_mode") && (m_intf_info[key].control_mode != b)) + { + if (b == "auto") + { + // port control mode auto + + if ((m_glbl_info.enable_auth) && (m_intf_info[key].link_status) && (!m_intf_info[key].config_created) && + (m_intf_info[key].capabilities == "authenticator") && (m_radiusServerInUse != "")) + { + /* create config file */ + createConfFile(key); + + /* update interfaces list */ + new_interfaces.push_back(key); + } + } + else + { + // pae role none + + if (m_intf_info[key].config_created) + { + /* delete config file */ + deleteConfFile(key); + + /* update interfaces list */ + del_interfaces.push_back(key); + } + } + m_intf_info[key].control_mode = b; + } + else if ((a == "server_timeout") && (m_intf_info[key].server_timeout != (unsigned int)stoi(b))) + { + m_intf_info[key].server_timeout = (unsigned int)stoi(b); + m_intf_info[key].server_timeout_modified = true; + } + else if ((a == "quiet_period") && (m_intf_info[key].quiet_period != (unsigned int)stoi(b))) + { + m_intf_info[key].quiet_period = (unsigned int)stoi(b); + m_intf_info[key].quiet_period_modified = true; + } + } + + /* update JSON for new_interfaces and del_interfaces */ + informHostapd("new", new_interfaces); + informHostapd("deleted", del_interfaces); + setPortDot1xTimeoutParams(); + } + else if (val == DEL_COMMAND) + { + SWSS_LOG_WARN("Unexpected DEL operation on PAC_PORT_CONFIG_TABLE, ignoring"); + continue; + } + } + + return true; +} + +bool HostapdMgr::processHostapdConfigGlobalTblEvent(Selectable *tbl) +{ + SWSS_LOG_ENTER(); + SWSS_LOG_DEBUG("Received an table config event on HOSTAPD_GLOBAL_CONFIG_TABLE table"); + + deque entries; + m_confHostapdGlobalTbl.pops(entries); + + SWSS_LOG_NOTICE("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + SWSS_LOG_NOTICE("enable_auth %d: ", m_glbl_info.enable_auth); + // Check through all the data + for (auto entry : entries) + { + string key = kfvKey(entry); + string val = kfvOp(entry); + + SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); + + if (val == SET_COMMAND) + { + // Look at the data that is sent for this key + for (auto i : kfvFieldsValues(entry)) + { + string a = fvField(i); + string b = fvValue(i); + + SWSS_LOG_DEBUG("Received %s as field and %s as value", a.c_str(), b.c_str()); + + vector interfaces; + + if (a == "dot1x_system_auth_control" ) + { + if (b == "true") + { + // dot1x enabled + if (!m_glbl_info.enable_auth) + { + SWSS_LOG_NOTICE("set m_glbl_info.enable_auth to 1"); + m_glbl_info.enable_auth = 1; + + for (auto const& entry: m_intf_info) + { + SWSS_LOG_NOTICE("--intf-- %s capabilities %s ctrl_mode %s admin_status %d link_status %d, global_auth %d", + entry.first.c_str(), m_intf_info[key].capabilities.c_str(), m_intf_info[key].control_mode.c_str(), + m_intf_info[key].admin_status, m_intf_info[key].link_status, m_glbl_info.enable_auth); + if ((entry.second.capabilities == "authenticator") && (entry.second.control_mode == "auto") && + (entry.second.link_status) && (!entry.second.config_created) && (m_radiusServerInUse != "")) + { + + /* create config file */ + createConfFile(entry.first); + + /* update interfaces list */ + interfaces.push_back(entry.first); + } + } + + /* Update JSON */ + + informHostapd("new", interfaces); + setPortDot1xTimeoutParams(); + + } + } + else if (b == "false") + { + // dot1x disabled + if (m_glbl_info.enable_auth) + { + m_glbl_info.enable_auth = 0; + SWSS_LOG_NOTICE("setting m_glbl_info.enable_auth to 0"); + + for (auto const& entry: m_intf_info) + { + SWSS_LOG_NOTICE("received false for intf %s capabilities %s ctrl_mode %s admin_status %d link_status %d, global_auth %d", + entry.first.c_str(), m_intf_info[key].capabilities.c_str(), m_intf_info[key].control_mode.c_str(),m_intf_info[key].admin_status, + m_intf_info[key].link_status, m_glbl_info.enable_auth); + + if (entry.second.config_created) + { + /* delete config file */ + deleteConfFile(entry.first); + + /* update interfaces list */ + interfaces.push_back(entry.first); + } + } + + /* Update JSON */ + informHostapd("deleted", interfaces); + } + } + } + } + } + else if (val == DEL_COMMAND) + { + SWSS_LOG_WARN("Unexpected DEL operation on HOSTAPD_GLOBAL_CONFIG_TABLE, ignoring"); + continue; + } + } + return true; +} + +string execute(string command) { + char buffer[128]; + string result = ""; + + SWSS_LOG_DEBUG("command is %s", command); + // Open pipe to file + FILE* pipe = popen(command.c_str(), "r"); + if (!pipe) { + return "popen failed!"; + } + + // read till end of process: + while (!feof(pipe)) { + + // use buffer to read and add to result + if (fgets(buffer, 128, pipe) != NULL) + result += buffer; + } + + pclose(pipe); + return result; +} + +static bool cmp(pair& a, + pair& b) +{ + return (stoi(a.second.server_priority) > stoi(b.second.server_priority)); +} + +void HostapdMgr::updateRadiusServer() { + + SWSS_LOG_ENTER(); + + SWSS_LOG_NOTICE("Update RADIUS Servers for HOSTAPD"); + + // Run over all radius information + vector> sortedMap; + + for (auto& item: m_radius_info.radius_auth_server_list) + { + item.second.server_priority = (item.second.server_priority == "") ? + "0": item.second.server_priority; + sortedMap.push_back(item); + } + + /* When no Radius servers configured reset m_radiusServerInUse field */ + if (0 == sortedMap.size()) + { + m_radiusServerInUse = ""; + } + + for (auto & item: m_radius_info.radius_auth_server_list) + { + struct addrinfo* result; + char ip[INET6_ADDRSTRLEN+1]; + void * src = NULL; + + item.second.config_ok = false; + + if (getaddrinfo(item.first.c_str(), NULL, NULL, &result) || result == NULL) + { + SWSS_LOG_WARN("skipped %s as it could not resolve.", item.first.c_str()); + continue; + } + + if(result->ai_family == AF_INET) + src = &((struct sockaddr_in*)result->ai_addr)->sin_addr; + else + src = &((struct sockaddr_in6*)result->ai_addr)->sin6_addr; + + inet_ntop(result->ai_family, src, ip, INET6_ADDRSTRLEN+1); + freeaddrinfo(result); + + //Check if radius server has key configured. If not, + // pick global key. If key does not exist, skip to next server. + if ((item.second.server_key == "") && (m_radius_info.m_radiusGlobalKey == "")) + { + SWSS_LOG_WARN("skipped %s as no key is configured.", item.first.c_str()); + continue; + } + + string radiusIp(ip); + item.second.config_ok = true; + item.second.server_ip = radiusIp; + // Check against in-use radius server and + // update hostapd if necessary. + if (item.second.server_priority > m_radiusServerInUseInfo.server_priority) + { + m_radiusServerInUse = ""; + } + + if (m_radiusServerInUse == "") + { + m_radiusServerInUse = radiusIp; + m_radiusServerInUseInfo.server_port = item.second.server_port; + m_radiusServerInUseInfo.server_key = m_radius_info.m_radiusGlobalKey; + m_radiusServerInUseInfo.server_priority = item.second.server_priority; + m_radiusServerInUseInfo.server_vrf = item.second.server_vrf; + m_radiusServerInUseInfo.server_source_intf = item.second.server_source_intf; + if (item.second.server_key != "") + { + m_radiusServerInUseInfo.server_key = item.second.server_key; + } + } + } + + if (m_glbl_info.enable_auth && m_radiusServerInUse != "") + { + // Update in use radius server and update hostapd. + vector interfaces; + for (auto const& entry: m_intf_info) + { + if ((m_glbl_info.enable_auth) && (entry.second.capabilities == "authenticator") && + (entry.second.control_mode == "auto") && + (entry.second.link_status)) + { + /* create config file */ + createConfFile(entry.first); + + /* update interfaces list */ + interfaces.push_back(entry.first); + } + } + + /* update JSON file */ + informHostapd("modified", interfaces); + setPortDot1xTimeoutParams(); + return; + } + + // Check if global auth is enabled or not + else if (!m_glbl_info.enable_auth || m_radiusServerInUse == "") + { + // No valid radius server found. Delete conf files and kill hostapd. + vector interfaces; + for (auto const& entry: m_intf_info) + { + if (entry.second.config_created) + { + /* delete config file */ + deleteConfFile(entry.first); + + /* update interfaces list */ + interfaces.push_back(entry.first); + } + } + + /* Update JSON */ + informHostapd("deleted", interfaces); + } + return; +} + +bool HostapdMgr::processRadiusServerTblEvent(Selectable *tbl) { + + SWSS_LOG_ENTER(); + SWSS_LOG_NOTICE("Received a RADIUS SERVER event"); + + deque entries; + m_confRadiusServerTable.pops(entries); + + SWSS_LOG_NOTICE("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + // Check through all the data + for (auto entry : entries) + { + string key = kfvKey(entry); + string val = kfvOp(entry); + string cmd(""); + + SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); + + if (val == SET_COMMAND) + { + m_radius_info.radius_auth_server_list[key].server_port = ""; + m_radius_info.radius_auth_server_list[key].server_key = ""; + m_radius_info.radius_auth_server_list[key].server_priority = ""; + m_radius_info.radius_auth_server_list[key].server_vrf = ""; + m_radius_info.radius_auth_server_list[key].server_source_intf = ""; + + // Look at the data that is sent for this key + for (auto i : kfvFieldsValues(entry)) + { + string a = fvField(i); + string b = fvValue(i); + + SWSS_LOG_NOTICE("Received %s as field and %s as value", a.c_str(), b.c_str()); + + if (a == "passkey") + { + DBus::Struct > ret; + ret = HostQuery_keyctl("pwDecrypt", b.c_str()); + if (0 != ret._1) + { + SWSS_LOG_ERROR("RADIUS server key is not decrypted properly and hence the HOSTAPD service is not steady."); + return false; + } + m_radius_info.radius_auth_server_list[key].server_key = ret._2; + } + else if (a == "auth_port") + { + m_radius_info.radius_auth_server_list[key].server_port = b; + } + else if (a == "priority") + { + m_radius_info.radius_auth_server_list[key].server_priority = b; + } + else if (a == "vrf") + { + m_radius_info.radius_auth_server_list[key].server_vrf = b; + } + else if (a == "src_intf") + { + m_radius_info.radius_auth_server_list[key].server_source_intf = b; + } + } + } + else if (val == DEL_COMMAND) + { + SWSS_LOG_WARN("DEL operation on RADIUS_SERVER table"); + + SWSS_LOG_NOTICE("Erasing server key"); + // sever deleted + m_radius_info.radius_auth_server_list.erase(key); + } + } + + updateRadiusServer(); + + return true; +} + +bool HostapdMgr::processRadiusGlobalTblEvent(Selectable *tbl) { + + SWSS_LOG_ENTER(); + SWSS_LOG_NOTICE("Received a RADIUS table event"); + string key(m_radius_info.m_radiusGlobalKey); + string nas_ip(m_radius_info.nas_ip); + + deque entries; + m_confRadiusGlobalTable.pops(entries); + + SWSS_LOG_NOTICE("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + // Check through all the data + for (auto entry : entries) + { + string key = kfvKey(entry); + string val = kfvOp(entry); + string cmd(""); + + // Global radius table modification results in a SET OP itself. + // Incoming field values will not have passkey or nas_ip. Hence, we intiialize to NULL + // so that incoming data will decide the final value. + m_radius_info.m_radiusGlobalKey = ""; + m_radius_info.nas_ip = ""; + + SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); + + if (val == SET_COMMAND) + { + // Look at the data that is sent for this key + for (auto i : kfvFieldsValues(entry)) + { + string a = fvField(i); + string b = fvValue(i); + + SWSS_LOG_NOTICE("Received %s as field and %s as value", a.c_str(), b.c_str()); + + if (a == "passkey") + { + DBus::Struct > ret; + ret = HostQuery_keyctl("pwDecrypt", b.c_str()); + if (0 != ret._1) + { + SWSS_LOG_ERROR("RADIUS global key is not decrypted properly and hence the HOSTAPD service is not steady."); + return false; + } + + m_radius_info.m_radiusGlobalKey = ret._2; + } + else if (a == "nas_ip") + { + m_radius_info.nas_ip = b; + } + } + } + else if (val == DEL_COMMAND) + { + SWSS_LOG_WARN("DEL operation on RADIUS table"); + + m_radius_info.m_radiusGlobalKey = ""; + m_radius_info.nas_ip = ""; + } + } + + // Since RADIUS config has been modified, deduce the new + // RADIUS server to be used and inform hostapd if required. + if ((m_radius_info.m_radiusGlobalKey != key) || (m_radius_info.nas_ip != nas_ip)) + { + updateRadiusServer(); + } + + return true; +} + +bool HostapdMgr::processMgmtIntfTblEvent(Selectable *tbl) +{ + std::deque entries; + m_mgmtIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on MGMT_INTERFACE Table", (int) entries.size()); + + // Removal of MGMT IP also is sent as a SET + m_radius_info.mgmt_ip = ""; + m_radius_info.mgmt_ipv6 = ""; + + for (auto entry : entries) + { + std::string key = kfvKey(entry); + SWSS_LOG_NOTICE("key %s", key.c_str()); + + auto tokens = tokenize(key, ':'); + SWSS_LOG_NOTICE("size %d", tokens.size()); + + // pick only IPv4 address of the management interface + if (2 == tokens.size()) + { + // eth0:a.b.c.d/mask + auto tokens1 = tokenize(tokens[1], '/'); + SWSS_LOG_NOTICE("Management IPv4 %s", tokens1[0].c_str()); + m_radius_info.mgmt_ip = tokens1[0]; + } + else if (tokens.size() > 2) + { + // eth0:2001::64/mask. Remove "eth0:" + string ipv6Str = key.substr(5); + + auto tokens1 = tokenize(ipv6Str, '/'); + SWSS_LOG_NOTICE("Management IPv6 %s", tokens1[0].c_str()); + m_radius_info.mgmt_ipv6 = tokens1[0]; + } + } + + string mgmt_intf("eth0"); + + if ((0 == m_radius_info.nas_ip.size()) || + (IsSourceIntf(mgmt_intf))) + { + SWSS_LOG_NOTICE("Interface %s address update.", mgmt_intf.c_str()); + updateRadiusServer(); + } + + return true; +} + +bool HostapdMgr::IsSourceIntf(const string interface) +{ + for (auto& item: m_radius_info.radius_auth_server_list) + { + if (item.second.server_source_intf == interface) + { + return true; + } + } + return false; +} + +bool HostapdMgr::processIntfTblEvent(Selectable *tbl) +{ + std::deque entries; + + if (tbl == ((Selectable *) & m_IntfTbl)) + { + m_IntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on INTERFACE Table", (int) entries.size()); + } + else if (tbl == ((Selectable *) & m_VlanIntfTbl)) + { + m_VlanIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on VLAN_INTERFACE Table", (int) entries.size()); + } + else if (tbl == ((Selectable *) & m_LoIntfTbl)) + { + m_LoIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on LOOPBACK_INTERFACE Table", (int) entries.size()); + } + else if (tbl == ((Selectable *) & m_PoIntfTbl)) + { + m_PoIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on PORTCHANNEL_INTERFACE Table", (int) entries.size()); + } + + for (auto entry : entries) + { + std::string key = kfvKey(entry); + SWSS_LOG_NOTICE("key %s", key.c_str()); + + auto key_tokens = tokenize(key, '|'); + SWSS_LOG_NOTICE("size %d", key_tokens.size()); + + if (2 == key_tokens.size()) + { + // Ethernet0|IPAddress + if (IsSourceIntf(key_tokens[0])) + { + auto ip_tokens = tokenize(key_tokens[1], '/'); + SWSS_LOG_NOTICE("Interface %s used as Source Interface. Address %s/%s", + key_tokens[0].c_str(), ip_tokens[0].c_str(), ip_tokens[1].c_str()); + updateRadiusServer(); + break; + } + } + } + + return true; +} + +void HostapdMgr::onMsg(int nlmsg_type, struct nl_object *obj) +{ + + SWSS_LOG_ENTER(); + + SWSS_LOG_DEBUG("nlmsg_type %d", nlmsg_type); + + if ((nlmsg_type != RTM_NEWLINK) && (nlmsg_type != RTM_DELLINK)) + { + return; + } + + struct rtnl_link *link = (struct rtnl_link *)obj; + string key = rtnl_link_get_name(link); + SWSS_LOG_DEBUG("key %s", getStdIfFormat(key).c_str()); + + if (key.compare(0, INTFS_PREFIX.length(), INTFS_PREFIX)) + { + return; + } + + unsigned int flags = rtnl_link_get_flags(link); + bool admin = flags & IFF_UP; + bool oper = flags & IFF_LOWER_UP; + + unsigned int ifindex = rtnl_link_get_ifindex(link); + char *type = rtnl_link_get_type(link); + + if (type) + { + SWSS_LOG_NOTICE("nlmsg type:%d key:%s admin:%d oper:%d ifindex:%d type:%s", + nlmsg_type, getStdIfFormat(key).c_str(), admin, oper, ifindex, type); + } + else + { + SWSS_LOG_NOTICE("nlmsg type:%d key:%s admin:%d oper:%d ifindex:%d ", + nlmsg_type, getStdIfFormat(key).c_str(), admin, oper, ifindex); + } + + + /* teamd instances are dealt in teamsyncd */ + if (type && !strcmp(type, TEAM_DRV_NAME)) + { + return; + } + + if(key.find("E") == string::npos) + { + SWSS_LOG_NOTICE("Skipping non Ethernet interface %s", key.c_str()); + return; + } + + string key1(""); + + if(key.length() > 8) + { + // Native format: Ethernetx + key1 = key; + } + else + { + key1 = "Eth" + key.substr(1,1) + '/' + key.substr(3); + } + + /* New interface handling */ + if (m_intf_info.find(key1) == m_intf_info.end()) + { + hostapd_intf_info_t intf; + + intf.control_mode = "force-authorized"; + intf.capabilities = "none"; + intf.admin_status = 0; + intf.link_status = 0; + intf.config_created = false; + + SWSS_LOG_NOTICE("New interface %s", key1.c_str()); + setPort(key1, intf); + } + + vector interfaces; + + /* Interface delete handling */ + if (nlmsg_type == RTM_DELLINK) + { + if (m_intf_info.find(key1) == m_intf_info.end()) + { + SWSS_LOG_NOTICE("Unknown interface %s for Delete event ", key1.c_str()); + return; + } + + SWSS_LOG_NOTICE("Delete %s event", key1.c_str()); + + if (m_intf_info[key1].config_created) + { + /* delete config file */ + deleteConfFile(key1); + + /* update interfaces list */ + interfaces.push_back(key1); + + /* update JSON file */ + informHostapd("deleted", interfaces); + } + + delPort(key1); + return; + } + + SWSS_LOG_NOTICE(": intf %s capabilities %s ctrl_mode %s admin_status %d link_status %d, global_auth %d admin %d oper %d", key1.c_str(), m_intf_info[key1].capabilities.c_str(), m_intf_info[key1].control_mode.c_str(),m_intf_info[key1].admin_status, m_intf_info[key1].link_status, m_glbl_info.enable_auth, admin, oper); + /* Set the admin state first*/ + if (admin != m_intf_info[key1].admin_status) + { + m_intf_info[key1].admin_status = admin; + } + + /* followed by the oper state */ + if (oper != m_intf_info[key1].link_status) + { + + m_intf_info[key1].link_status = oper; + + if ((m_glbl_info.enable_auth) && (m_intf_info[key1].capabilities == "authenticator") && + (m_intf_info[key1].control_mode == "auto")) + { + + if ((m_intf_info[key1].link_status) && (!m_intf_info[key1].config_created) && + (m_radiusServerInUse != "")) + { + /* create config file */ + createConfFile(key1); + + /* update interfaces list */ + interfaces.push_back(key1); + + /* update JSON file */ + informHostapd("new", interfaces); + setPortDot1xTimeoutParams(); + } + /* down't bring down hostapd interface when admin state goes down. + * it will get deleted with RTM_DELLINK. + */ + } + } +} + +void HostapdMgr::killHostapd(void) +{ + pid_t pid = getHostapdPid(); + if (pid) + { + kill(pid, 9); + } +} + +void HostapdMgr::setPort(const string & alias, const hostapd_intf_info_t & port) +{ + SWSS_LOG_ENTER(); + m_intf_info[alias] = port; +} + +void HostapdMgr::delPort(const string & alias) +{ + SWSS_LOG_ENTER(); + m_intf_info.erase(alias); +} + +void HostapdMgr::setPortDot1xTimeoutParams() +{ + SWSS_LOG_ENTER(); + if (0 == active_intf_cnt) + { + return; + } + + pid_t pid = getHostapdPid(); + + if (0 == pid) + { + return; + } + for (auto& item: m_intf_info) + { + if (true == item.second.config_created) + { + if ((true == item.second.server_timeout_modified) || + (PAC_SERVER_TIMEOUT_DEF != item.second.server_timeout)) + { + std::string s = std::to_string(item.second.server_timeout); + hostapdDot1xWpaEventSend(item.first, HOSTAPD_SERVER_TIMEOUT, s); + item.second.server_timeout_modified = false; + } + if ((true == item.second.quiet_period_modified) || + (PAC_QUIET_PERIOD_DEF != item.second.quiet_period)) + { + std::string s = std::to_string(item.second.quiet_period); + hostapdDot1xWpaEventSend(item.first, HOSTAPD_QUIET_PERIOD, s); + item.second.quiet_period_modified = false; + } + } + } +} + +static bool file_exists(const string& file_name) +{ + ifstream ifile; + + ifile.open(file_name); + + if(ifile) + { + return true;; + } + else + { + return false; + } +} + +static string getHostIntfName(string ifname) +{ + size_t pos; + const std::string find = "/"; + const std::string replace = "_"; + const std::string e = "E"; + const std::string ethernet = "Eth"; + + if(ifname.length() > 8) + { + // Ethernet0 format + } + else + { + // look for Eth1/1 format + pos = ifname.find(find); + + if (pos != string::npos) + { + while(pos != string::npos) + { + ifname.replace(pos, replace.size(), replace); + pos = ifname.find(find, pos + replace.size()); + } + ifname.replace(0, ethernet.size(), e); + } + else + { + return ifname; + } + } + return ifname; +} + +void HostapdMgr::informHostapd(const string& type, const vector & interfaces) +{ + SWSS_LOG_ENTER(); + + string content; + pid_t pid = 0; + string pid_file(HOSTAPD_PID_FILE); + + SWSS_LOG_NOTICE("informHostapd(): Interface size %d", (int) interfaces.size()); + + if (!interfaces.size()) { + return; + } + + + string file; + string cmd; + string cmd_pid; + + file = "/etc/hostapd/hostapd_config.json"; + + cmd = "rm -f "; + cmd += file; + + + if (start_hostapd) + { + int rc = 0; + start_hostapd = false; + + if (system(cmd.c_str())) + { + SWSS_LOG_WARN("command %s could not be executed.", cmd.c_str()); + } + else + { + SWSS_LOG_NOTICE("hostapd_config json file is deleted successfully before starting hostapd"); + } + + cmd_pid = "rm -f "; + cmd_pid += HOSTAPD_PID_FILE; + + SWSS_LOG_NOTICE("Executing %s ", cmd_pid.c_str()); + + rc = system(cmd_pid.c_str()); + SWSS_LOG_NOTICE("rc = %d, errno %d(%s) ", rc, errno, strerror(errno)); + + if (rc < 0) + { + SWSS_LOG_WARN("%s could not be deleted.", pid_file.c_str()); + } + + // start hostapd + + content = "hostapd -d -P "; + content += HOSTAPD_PID_FILE; + content += " "; + + for(auto item: interfaces) + { + SWSS_LOG_NOTICE("starting hostapd on %s ", item.c_str()); + content += "/etc/hostapd/"; + content += getHostIntfName(item); + content += ".conf "; + } + + content += " & " ; + + SWSS_LOG_NOTICE("Executing: %s ", content.c_str()); + + rc = system(content.c_str()); + SWSS_LOG_NOTICE("rc = %d, errno %d(%s) ", rc, errno, strerror(errno)); + + if (rc < 0) + { + SWSS_LOG_WARN("hostapd could not be started."); + } + + pid = getHostapdPid(); + if (pid) + { + SWSS_LOG_NOTICE("hostapd started with PID %d ", pid); + } + else + { + SWSS_LOG_NOTICE("hostapd could not be started: PID %d ", pid); + } + + if (0 == waitForHostapdInit(pid)) + { + SWSS_LOG_NOTICE("hostapd initialized with PID %d ", pid); + } + else + { + SWSS_LOG_NOTICE("hostapd could not be initialized with PID %d ", pid); + } + } + else if (stop_hostapd) + { + // kill hostapd + + stop_hostapd = false; + + if (system(cmd.c_str())) + { + SWSS_LOG_WARN("command %s could not be executed.", cmd.c_str()); + } + else + { + SWSS_LOG_NOTICE("hostapd_config json file is deleted successfully before stopping hostapd"); + } + + + pid = getHostapdPid(); + + if (pid) + { + SWSS_LOG_NOTICE("terminating hostapd PID %d ", pid); + kill(pid, 9); + } + else + { + SWSS_LOG_NOTICE("hostapd PID could not be found: PID %d ", pid); + } + } + else + { + string file; + unsigned int cnt = 10; + + file = "/etc/hostapd/hostapd_config.json"; + + while (cnt) + { + if (file_exists(file)) + { + SWSS_LOG_NOTICE("JSON file still exists. wait till the old file is read (%d)", cnt); + cnt--; + sleep(1); + } + else + { + break; + } + } + + if (0 == cnt) + { + SWSS_LOG_NOTICE("JSON file still exists. not sending signal 1 to hostapd (%d)", cnt); + return; + } + + if ((type == "new") || (type == "modified")){ + + content = "{\n"; + content += "\""; + content += (type + "_interfaces\": \n"); + content += "[\n"; + + for(auto item: interfaces) { + content += "{\n"; + + content += "\"if_name\": "; + + content += "\""; + content += (getHostIntfName(item) + "\",\n"); + + content += "\"path\": "; + content += "\"/etc/hostapd/"; + content += getHostIntfName(item); + content += ".conf\""; + content += "\n"; + content += "}"; + + if (item.compare(interfaces.back())) { + content += ","; + } + + content += "\n"; + } + content += "]\n"; + content += "}\n"; + + } + else if (type == "deleted") { + content = "{\n"; + content += "\""; + content += (type + "_interfaces\": \n"); + content += "[\n"; + + for(auto item: interfaces) { + content += "{\n"; + content += "\"if_name\": "; + content += "\""; + content += (getHostIntfName(item) + "\"\n"); + + content += "}"; + + + if (item.compare(interfaces.back())) { + content += ","; + } + + content += "\n"; + } + content += "]\n"; + content += "}\n"; + } + else { + return; + } + + // Write to the file + writeToFile(file, content); + + SWSS_LOG_NOTICE("sending Signal 1 to hostapd"); + + // signal + sendSignal(); + } +} + +void HostapdMgr::createConfFile(const string& intf) +{ + SWSS_LOG_ENTER(); + + string file; + string content; + bool exists = false; + + file = "/etc/hostapd/"; + file += (getHostIntfName(intf) + ".conf"); + + content = "interface="; + content += (getHostIntfName(intf) + "\n"); + + content += "driver=wired\n"; + content += "logger_stdout=63\n"; // 0x3f: Turn on for all hostapd modules + content += "logger_stdout_level=2\n"; + content += "logger_syslog=-1\n"; + content += "logger_syslog_level=2\n"; + content += "ieee8021x=1\n"; + + content += "ctrl_interface=/var/run/hostapd\n"; + content += "use_pae_group_addr=0\n"; + + string nas_ip(""); + string nas_id(""); + + if (m_radius_info.nas_ip.size()) + { + nas_ip = m_radius_info.nas_ip; + nas_id = m_radius_info.nas_ip; + } + else if (m_radius_info.mgmt_ip.size()) + { + nas_ip = m_radius_info.mgmt_ip; + nas_id = m_radius_info.mgmt_ip; + } + else if (m_radius_info.mgmt_ipv6.size()) + { + nas_ip = m_radius_info.mgmt_ipv6; + nas_id = m_radius_info.mgmt_ipv6; + } + + if (nas_ip.size() && nas_id.size()) + { + content += "own_ip_addr="; + content += (nas_ip + "\n"); + content += "nas_identifier="; + content += (nas_id + "\n"); + } + + vector> auth_sortedMap; + for (auto& item: m_radius_info.radius_auth_server_list) + { + if (false == item.second.config_ok) + { + continue; + } + auth_sortedMap.push_back(item); + } + + if (0 != auth_sortedMap.size()) + { + sort(auth_sortedMap.begin(), auth_sortedMap.end(), cmp); + } + + for (auto const& item: auth_sortedMap) + { + if ((item.second.server_key == "") && (m_radius_info.m_radiusGlobalKey == "")) + { + SWSS_LOG_WARN("Update in config file skipped %s as no key is configured.", item.first.c_str()); + continue; + } + content += "auth_server_addr="; + content += (item.second.server_ip.c_str()); + content += "\n"; + + content += "auth_server_port="; + content += (item.second.server_port + "\n"); + + content += "auth_server_shared_secret="; + if (item.second.server_key == "") + { + content += (m_radius_info.m_radiusGlobalKey + "\n"); + } + else + { + content += (item.second.server_key + "\n"); + } + + if (item.second.server_vrf != "") + { + content += "auth_server_vrf="; + content += (item.second.server_vrf + "\n"); + } + + if (item.second.server_source_intf != "") + { + content += "auth_server_source_interface="; + content += (getHostIntfName(item.second.server_source_intf) + "\n"); + } + } + + vector> sortedMap; + for (auto& item: m_radius_info.radius_acct_server_list) + { + item.second.server_priority = (item.second.server_priority == "") ? + "0": item.second.server_priority; + sortedMap.push_back(item); + } + + for (auto const& item: sortedMap) + { + content += "acct_server_addr="; + content += (item.first + "\n"); + + content += "acct_server_port="; + content += (item.second.server_port + "\n"); + + content += "acct_server_shared_secret="; + content += (item.second.server_key + "\n"); + } + + SWSS_LOG_NOTICE("active intf count %d ", active_intf_cnt); + if (file_exists(file)) + { + exists = true; + } + + // Write to the file + writeToFile(file, content); + + if (!active_intf_cnt) + { + SWSS_LOG_NOTICE("setting start hostapd flag to true"); + start_hostapd = true; + } + + if (false == exists) + { + active_intf_cnt++; + SWSS_LOG_NOTICE("incrementing intf count %d", active_intf_cnt); + } + + m_intf_info[intf].config_created = true; +} + +void HostapdMgr::deleteConfFile(const string& intf) +{ + SWSS_LOG_ENTER(); + + string file; + string cmd; + + file = "/etc/hostapd/"; + file += (getHostIntfName(intf) + ".conf"); + + cmd = "rm -f "; + cmd += file; + + if (system(cmd.c_str())) + { + SWSS_LOG_WARN("command %s could not be executed.", cmd.c_str()); + } + + if (active_intf_cnt) + { + SWSS_LOG_NOTICE("decrementing intf count %d", active_intf_cnt); + active_intf_cnt--; + } + + if (!active_intf_cnt) + { + stop_hostapd = true; + SWSS_LOG_NOTICE("setting stop hostapd flag to true"); + } + m_intf_info[intf].config_created = false; +} + +void HostapdMgr::writeToFile(const string& filename, const string& value) +{ + SWSS_LOG_ENTER(); + ofstream file; + + file.open(filename, ofstream::out | ofstream::trunc); + + // Write to the file + file << value; + + // Close the file + file.close(); +} + +void HostapdMgr::sendSignal(void) +{ + SWSS_LOG_ENTER(); + + pid_t pid = 0; + + if (pid = getHostapdPid()) + { + kill(pid, 1); + } +} + +pid_t HostapdMgr::getHostapdPid(void) +{ + SWSS_LOG_ENTER(); + pid_t pid = 0; + int count = 10; + + while (system("pidof hostapd > ./temp.out")) + { + SWSS_LOG_WARN("command could not be executed. Remaining retry(%d)..", count--); + usleep(100*1000); + + if (count <=0) + { + return 0; + } + } + + ifstream infile("./temp.out"); + if (!infile.is_open()) + { + SWSS_LOG_WARN("The PID file is not readable"); + return 0; + } + + string line; + getline(infile, line); + if (line.empty()) + { + SWSS_LOG_WARN("The PID file is empty"); + } + else + { + /*Store the PID value */ + pid = stoi(line, nullptr, 10); + } + + return pid; +} + +int HostapdMgr::waitForHostapdInit(pid_t hostapd_pid) +{ + SWSS_LOG_ENTER(); + pid_t pid = 0; + int count = 10; + string pid_file(HOSTAPD_PID_FILE); + + while (!file_exists(pid_file)) + { + SWSS_LOG_WARN("%s not found. Remaining retry(%d)..", pid_file.c_str(), count--); + usleep(100*1000); + + if (count <=0) + { + SWSS_LOG_WARN("Max retries exceeded to read from %s.", pid_file.c_str()); + return -1; + } + } + + ifstream infile(HOSTAPD_PID_FILE); + string line; + getline(infile, line); + if (line.empty()) + { + SWSS_LOG_WARN("The PID file %s is empty", pid_file.c_str()); + return -1; + } + + /*Store the PID value */ + pid = stoi(line, nullptr, 10); + + SWSS_LOG_NOTICE("%s has pid %d", pid_file.c_str(), pid); + SWSS_LOG_NOTICE("hostapd_pid = %d", hostapd_pid); + + return (pid == hostapd_pid)? 0 : -1; +} + +void HostapdMgr::hostapdDot1xWpaEventSend(const string& interface, const string& event, string& val) +{ + size_t len = 0; + char buf[128] = {'\0'}; + char cmd[128] = {'\0'}; + char bcast_addr[] = "FF:FF:FF:FF:FF:FF"; + string intf = getHostIntfName(interface); + + SWSS_LOG_DEBUG("Hostapd %s event %s = %s ", intf.c_str(), event.c_str(), val.c_str()); + snprintf(cmd, sizeof(cmd), "EAPOL_SET %s %s %s", bcast_addr, event.c_str(), val.c_str()); + + if (0 == hostapdWpaSyncSend(intf.c_str(), cmd, buf, &len)) + { + if (0 == strncmp("OK", buf, strlen("OK"))) + { + SWSS_LOG_INFO("Hostapd %s event %s = %s set successfully.", intf.c_str(), event.c_str(), val.c_str()); + return; + } + } + SWSS_LOG_WARN("Hostapd %s event %s = %s set failed.", intf.c_str(), event.c_str(), val.c_str()); +} + +int HostapdMgr::hostapdWpaSyncSend(const char *ctrl_ifname, const char * cmd, char *buf, size_t *len) +{ + static struct wpa_ctrl *ctrl_conn; + int ret; + char sock_file[128]; + + memset(sock_file, 0, sizeof(sock_file)); + sprintf(sock_file, "/var/run/hostapd/%s", ctrl_ifname); + + ctrl_conn = wpa_ctrl_open(sock_file); + if (NULL == ctrl_conn) + { + SWSS_LOG_NOTICE("Not connected to hostapd - command dropped.. retrying.."); + usleep(10 * 1000); + + ctrl_conn = wpa_ctrl_open(sock_file); + + if (NULL == ctrl_conn) + { + SWSS_LOG_NOTICE("Not connected to hostapd - command dropped..\n"); + return -1; + } + } + + *len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, len, NULL); + if (ret == -2) + { + SWSS_LOG_NOTICE("'%s' command timed out.\n", cmd); + return -2; + } + else if (ret < 0) + { + SWSS_LOG_NOTICE("'%s' command failed.\n", cmd); + return -1; + } + if (1) + { + buf[*len] = '\0'; + SWSS_LOG_NOTICE("hostapd reply %s", buf); + } + wpa_ctrl_close(ctrl_conn); + return 0; +} diff --git a/hostapdmgr/hostapdmgr.h b/hostapdmgr/hostapdmgr.h new file mode 100644 index 0000000..b083079 --- /dev/null +++ b/hostapdmgr/hostapdmgr.h @@ -0,0 +1,142 @@ +/* + * Copyright 2019 Broadcom Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HOSTAPDMGR_H_ +#define _HOSTAPDMGR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "netmsg.h" +#include "redisapi.h" + +using namespace swss; +using namespace std; + +#define REAUTH_PERIOD 3600 +#define PAC_SERVER_TIMEOUT_DEF 30 +#define PAC_QUIET_PERIOD_DEF 30 + +void hostapdHandleDumpError(void *cbData); + +typedef struct hostapd_glbl_info_s { + unsigned int enable_auth; +}hostapd_glbl_info_t; + +typedef struct hostapd_intf_info_s { + std::string capabilities; + std::string control_mode; + unsigned int admin_status; + unsigned int link_status; + unsigned int quiet_period = PAC_QUIET_PERIOD_DEF; + unsigned int server_timeout = PAC_SERVER_TIMEOUT_DEF; + bool server_timeout_modified = false; + bool quiet_period_modified = false; + bool config_created; +}hostapd_intf_info_t; + +typedef struct radius_server_info_s { + std::string server_port; + std::string server_key; + std::string server_priority; + std::string server_ip; + std::string server_vrf; + std::string server_source_intf; + bool config_ok; +}radius_server_info_t; + +typedef std::map radius_server_info_map_t; + +typedef struct radius_info_s { + string m_radiusGlobalKey; + std::string nas_ip; + std::string mgmt_ip; + std::string mgmt_ipv6; + radius_server_info_map_t radius_auth_server_list; + radius_server_info_map_t radius_acct_server_list; +}radius_info_t; + +typedef std::map hostapd_intf_info_map_t; + +class HostapdMgr : public NetMsg +{ +public: + HostapdMgr(DBConnector *configDb, DBConnector *appDb); + std::vector getSelectables(); + bool processDbEvent(Selectable *source); + virtual void onMsg(int nlmsg_type, struct nl_object *obj); + void killHostapd(void); + void showDebugInfo(DebugShCmd *cmd, string intf); + string getStdIfFormat(string intf); + +private: + //tables this component listens to + SubscriberStateTable m_confHostapdPortTbl; + SubscriberStateTable m_confHostapdGlobalTbl; + SubscriberStateTable m_confRadiusServerTable; + SubscriberStateTable m_confRadiusGlobalTable; + SubscriberStateTable m_mgmtIntfTbl; + SubscriberStateTable m_IntfTbl; + SubscriberStateTable m_VlanIntfTbl; + SubscriberStateTable m_LoIntfTbl; + SubscriberStateTable m_PoIntfTbl; + + hostapd_glbl_info_t m_glbl_info; + hostapd_intf_info_map_t m_intf_info; + radius_info_t m_radius_info; + string m_radiusServerInUse; + radius_server_info_t m_radiusServerInUseInfo; + unsigned int active_intf_cnt; + + bool start_hostapd; + bool stop_hostapd; + + void setPort(const string & alias, const hostapd_intf_info_t &intf_info); + void delPort(const string & alias); + + // DB Event handler functions + bool processHostapdConfigPortTblEvent(Selectable *tbl); + bool processHostapdConfigGlobalTblEvent(Selectable *tbl); + bool processRadiusServerTblEvent(Selectable *tbl); + bool processRadiusGlobalTblEvent(Selectable *tbl); + bool processMgmtIntfTblEvent(Selectable *tbl); + bool processIntfTblEvent(Selectable *tbl); + + void writeToFile(const string& filename, const string& value); + void informHostapd(const string& type, const vector & interfaces); + void createConfFile(const string& intf); + void deleteConfFile(const string& intf); + pid_t getHostapdPid(void); + int waitForHostapdInit(pid_t hostapd_pid); + void sendSignal(void); + void updateRadiusServer(); + void hostapdDot1xWpaEventSend(const string& interface, const string& event, string& val); + int hostapdWpaSyncSend(const char *ctrl_ifname, const char * cmd, char *buf, size_t *len); + void setPortDot1xTimeoutParams(); + bool IsSourceIntf(const string interface); +}; + +#endif // _HOSTAPDMGR_H_ diff --git a/hostapdmgr/hostapdmgr_main.cpp b/hostapdmgr/hostapdmgr_main.cpp new file mode 100644 index 0000000..d570c11 --- /dev/null +++ b/hostapdmgr/hostapdmgr_main.cpp @@ -0,0 +1,135 @@ +/* + * Copyright 2019 Broadcom Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "netdispatcher.h" +#include "netlink.h" +#include "select.h" +#include +#include "hostapdmgr.h" +#include +#include "ebpf/libebpf.h" + +int main(int argc, char *argv[]) +{ + swss::DBConnector configDb("CONFIG_DB", 0); + swss::DBConnector stateDb("STATE_DB", 0); + swss::DBConnector appDb("APPL_DB", 0); + swss::DBConnector log_db(LOGLEVEL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + HostapdMgr hostapd(&configDb, &appDb); + + DebugShCmdHandler dbg_hdlr(&log_db, "HOSTAPDMGRD"); + + try + { + SWSS_LOG_NOTICE("-----Starting HostapdMgr-----"); + + //register for the table events + swss::Select s; + s.addSelectables(hostapd.getSelectables()); + s.addSelectables(dbg_hdlr.getSelectables()); + + //register for the table events + NetLink netlink; + netlink.registerGroup(RTNLGRP_LINK); + netlink.dumpRequest(RTM_GETLINK); + netlink.setDumpIntrErrorCallback(hostapdHandleDumpError, &netlink); + attach_ebpf_filter(netlink.getFd(), "/lib/ebpf/pac_filter.bpf"); + SWSS_LOG_DEBUG("Attaching pac ebpf filter"); + + // kill any stale hostapd + hostapd.killHostapd(); + + // cleanup stale hostapd conf files + string cmd = "rm -f /etc/hostapd/E*.conf"; + if (system(cmd.c_str())) + { + SWSS_LOG_WARN("Could not delete stale conf files."); + } + + // remove stale hostapd_config.json + cmd = "rm -f /etc/hostapd/hostapd_config.json"; + if (system(cmd.c_str())) + { + SWSS_LOG_WARN("Could not delete stale hostapd_config.json file."); + } + + // cleanup stale hostapd socket files + cmd = "rm -f /var/run/hostapd/E*"; + if (system(cmd.c_str())) + { + SWSS_LOG_WARN("Could not delete stale hostapd socket files."); + } + + // App Marking closest UP status + Table feat_tbl(&stateDb, STATE_FEATURE_TABLE_NAME); + std::vector attrs; + FieldValueTuple up_ready_status("UP_STATUS", "True"); + FieldValueTuple fail_reason("FAIL_REASON", ""); + char buffer[100]; + std::time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = gmtime(&rawtime); + strftime(buffer, 100, "%Y-%m-%d %H:%M:%S", timeinfo); + FieldValueTuple time("TIME", string(buffer)); + attrs.push_back(up_ready_status); + attrs.push_back(fail_reason); + attrs.push_back(time); + feat_tbl.set("hostapdmgr", attrs); + SWSS_LOG_NOTICE("hostapdmgr marked its UP Status to True"); + + NetDispatcher::getInstance().registerMessageHandler(RTM_NEWLINK, (swss::NetMsg*)&hostapd); + NetDispatcher::getInstance().registerMessageHandler(RTM_DELLINK, (swss::NetMsg*)&hostapd); + + s.addSelectable(&netlink); + + //wait for the events and process them + while (1) + { + SWSS_LOG_NOTICE("Waiting for HOSTAPD Table Events"); + + swss::Selectable *sel = NULL; + int ret; + + ret = s.select(&sel); + + if (dbg_hdlr.isDebugSelectable(sel)) + { + dbg_hdlr.process(sel); + } + else if (sel != &netlink) + { + //Pass on the processing to the Hostapd Manager + hostapd.processDbEvent(sel); + } + } + } + catch (const exception &e) + { + SWSS_LOG_ERROR("Runtime error: %s", e.what()); + } + + return -1; +} + +void hostapdHandleDumpError(void *cbData) +{ + SWSS_LOG_ENTER(); + NetLink *netlink = (NetLink *)cbData; + SWSS_LOG_NOTICE("Netlink dump failed with NLE_DUMP_INTR, resending dump request"); + netlink->dumpRequest(RTM_GETLINK); +} diff --git a/mabmgr/mabmgr.cpp b/mabmgr/mabmgr.cpp new file mode 100644 index 0000000..866e8be --- /dev/null +++ b/mabmgr/mabmgr.cpp @@ -0,0 +1,1051 @@ +/* + * Copyright 2019 Broadcom Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "mabmgr.h" +#include "mab_api.h" +#include "mab_exports.h" +#include "mab_include.h" +#include "datatypes.h" +#include "nimapi.h" +#include +#include +#include "tokenize.h" +#include "fpSonicUtils.h" + +#define MABD_CMD_BUFFSZ 2048 +MabMgr *mab; + +const string INTFS_PREFIX = "E"; + +DEBUGSH_CLI(MabMgrRadiusStats, + "show system internal mabmgr radius-stats", + SHOW_COMMAND, + SYSTEM_DEBUG_COMMAND, + INTERNAL_COMMAND, + "MabMgr related commands", + "Radius stats") +{ + mab->showDebugInfo(this); +} + + +mabGlobalConfigCacheParams_t MabMgr::mabGlobalConfigTable = { MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF, + MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF, + MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF }; + +MabMgr::MabMgr(DBConnector *configDb, DBConnector *stateDb, DBConnector *appDb) : + m_confMabPortTbl(configDb, "MAB_PORT_CONFIG_TABLE"), + m_confMabGlobalTbl(configDb, "MAB_GLOBAL_CONFIG_TABLE"), + m_confRadiusServerTable(configDb, "RADIUS_SERVER"), + m_confRadiusGlobalTable(configDb, "RADIUS"), + m_mgmtIntfTbl(appDb, "MGMT_INTF_TABLE"), + m_IntfTbl(configDb, CFG_INTF_TABLE_NAME), + m_VlanIntfTbl(configDb, CFG_VLAN_INTF_TABLE_NAME), + m_LoIntfTbl(configDb, CFG_LOOPBACK_INTERFACE_TABLE_NAME), + m_PoIntfTbl(configDb, CFG_LAG_INTF_TABLE_NAME) { + + Logger::linkToDbNative("mabmgr"); + SWSS_LOG_DEBUG("Installing MabMgr commands"); + mab = this; + DebugShCmd::install(new MabMgrRadiusStats()); + +} + +void MabMgr::showDebugInfo(DebugShCmd *cmd) +{ + char buffer[MABD_CMD_BUFFSZ]; + + memset(buffer, 0, sizeof(buffer)); + + if (L7_SUCCESS == mabRadiusClientGetStats(buffer, sizeof(buffer))) + { + DEBUGSH_OUT(cmd, "Dumping MabMgr radius stats\n\n"); + DEBUGSH_OUT(cmd, "==============================================\n"); + + DEBUGSH_OUT(cmd, "%s", buffer); + DEBUGSH_OUT(cmd, "\n==============================================\n\n"); + } +} + +std::vector MabMgr::getSelectables() { + vector selectables{ &m_confMabPortTbl, &m_confMabGlobalTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable, + &m_mgmtIntfTbl, &m_IntfTbl, &m_VlanIntfTbl, &m_PoIntfTbl, &m_LoIntfTbl }; + return selectables; +} + + +bool MabMgr::processDbEvent(Selectable *tbl) { + + SWSS_LOG_DEBUG("Received a MAB Database event"); + + //check the source table and accordingly invoke the appropriate handlers + + if (tbl == ((Selectable *) & m_confMabPortTbl)) { + return processMabConfigPortTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_confMabGlobalTbl)) { + return processMabConfigGlobalTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_confRadiusServerTable)) { + return processRadiusServerTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_confRadiusGlobalTable)) { + return processRadiusGlobalTblEvent(tbl); + } + + if (tbl == ((Selectable *) & m_mgmtIntfTbl)) { + return processMgmtIntfTblEvent(tbl); + } + + if ((tbl == ((Selectable *) & m_IntfTbl)) || + (tbl == ((Selectable *) & m_VlanIntfTbl)) || + (tbl == ((Selectable *) & m_LoIntfTbl)) || + (tbl == ((Selectable *) & m_PoIntfTbl))) { + return processIntfTblEvent(tbl); + } + + SWSS_LOG_DEBUG("Received event UNKNOWN to MAB, ignoring "); + return false; +} + +//Process the config db table events + +bool MabMgr::processMabConfigPortTblEvent(Selectable *tbl) +{ + SWSS_LOG_ENTER(); + SWSS_LOG_DEBUG("Received a table config event on MAB_PORT_CONFIG_TABLE table"); + + std::deque entries; + m_confMabPortTbl.pops(entries); + + SWSS_LOG_DEBUG("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + // Check through all the data + for (auto entry : entries) + { + std::string key = kfvKey(entry); + std::string op = kfvOp(entry); + bool task_result = false; + L7_uint32 intIfNum; + + SWSS_LOG_DEBUG("Received %s as key and %s as OP", key.c_str(), op.c_str()); + + if(key.find(INTFS_PREFIX) == string::npos) + { + SWSS_LOG_NOTICE("Invalid key format. No 'E' prefix: %s", key.c_str()); + continue; + } + + if(fpGetIntIfNumFromHostIfName(key.c_str(), &intIfNum) != L7_SUCCESS) + { + SWSS_LOG_NOTICE("Unable to get the internal interface number for %s.", key.c_str()); + continue; + } + + if (op == SET_COMMAND) + { + task_result = doMabPortTableSetTask(entry, intIfNum); + } + else if (op == DEL_COMMAND) + { + task_result = doMabPortTableDeleteTask(entry, intIfNum); + } + if (!task_result) + return false; + } + return true; +} + +bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum) +{ + SWSS_LOG_ENTER(); + const std::string & key = kfvKey(t); + + // Update mabPortConfigCache cache with incoming table data + mabPortConfigCacheParams_t mabPortConfigCache; + mabPortConfigCache.mab_enable = MABMGR_MAB_PORT_ENABLE_DEF; + mabPortConfigCache.mab_auth_type = MABMGR_MAB_PORT_AUTH_TYPE_DEF; + mabPortConfigCache.mab_server_timeout = MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF; + + for (auto item = kfvFieldsValues(t).begin(); item != kfvFieldsValues(t).end(); item++) + { + const std::string & field = fvField(*item); + const std::string & value = fvValue(*item); + + if (field == "mab_enable") + { + if (value == "true") + mabPortConfigCache.mab_enable = L7_ENABLE; + else if (value == "false") + mabPortConfigCache.mab_enable = L7_DISABLE; + else { + SWSS_LOG_WARN("Invalid configuration option received for mab enable: %s", value.c_str()); + continue; + } + } + if (field == "mab_auth_type") + { + if (value == "pap") + mabPortConfigCache.mab_auth_type= L7_AUTHMGR_PORT_MAB_AUTH_TYPE_PAP; + else if (value == "chap") + mabPortConfigCache.mab_auth_type = L7_AUTHMGR_PORT_MAB_AUTH_TYPE_CHAP; + else if (value == "eap-md5") + mabPortConfigCache.mab_auth_type = L7_AUTHMGR_PORT_MAB_AUTH_TYPE_EAP_MD5; + else { + SWSS_LOG_WARN("Invalid configuration option received for mab auth type: %s", value.c_str()); + continue; + } + } + if (field == "server_timeout") + { + mabPortConfigCache.mab_server_timeout = (unsigned int)stoi(value); + } + } + + mabPortConfigTableMap::iterator iter = m_mabPortConfigMap.find(key); + if(iter == m_mabPortConfigMap.end()) + { + m_mabPortConfigMap.insert(pair(key, mabPortConfigCache)); + mabPortConfigTableMap::iterator iter = m_mabPortConfigMap.find(key); + + if(mabPortConfigCache.mab_enable != MABMGR_MAB_PORT_ENABLE_DEF) + { + if (L7_SUCCESS != mabPortMABEnableSet(intIfNum, mabPortConfigCache.mab_enable)) + { + iter->second.mab_enable = MABMGR_MAB_PORT_ENABLE_DEF; + SWSS_LOG_ERROR("Unable to enable MAB operationally."); + } + } + if(mabPortConfigCache.mab_auth_type != MABMGR_MAB_PORT_AUTH_TYPE_DEF) + { + if (L7_SUCCESS != mabPortMABAuthTypeSet(intIfNum, mabPortConfigCache.mab_auth_type)) + { + iter->second.mab_auth_type = MABMGR_MAB_PORT_AUTH_TYPE_DEF; + SWSS_LOG_ERROR("Unable to set MAB authentication type operationally."); + } + } + if(MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF != mabPortConfigCache.mab_server_timeout) + { + if (L7_SUCCESS != mabPortMABServerTimeoutSet(intIfNum, mabPortConfigCache.mab_server_timeout)) + { + iter->second.mab_server_timeout = MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF; + SWSS_LOG_ERROR("Unable to set MAB port server timeout."); + } + } + } + else //Interface entry already exists in local cache, check for any parameter change for Add/Update/Delete + { + // mab_enable + if (((iter->second.mab_enable == MABMGR_MAB_PORT_ENABLE_DEF) && + (mabPortConfigCache.mab_enable != MABMGR_MAB_PORT_ENABLE_DEF)) || + ((iter->second.mab_enable != MABMGR_MAB_PORT_ENABLE_DEF) && + (mabPortConfigCache.mab_enable != iter->second.mab_enable))) + { + if (L7_SUCCESS == mabPortMABEnableSet(intIfNum, mabPortConfigCache.mab_enable)) + { + iter->second.mab_enable = mabPortConfigCache.mab_enable; + } + else + { + SWSS_LOG_ERROR("Unable to enable/disable MAB operationally."); + return false; + } + } + // mab_auth_type + if (((iter->second.mab_auth_type == MABMGR_MAB_PORT_AUTH_TYPE_DEF) && + (mabPortConfigCache.mab_auth_type != MABMGR_MAB_PORT_AUTH_TYPE_DEF)) || + ((iter->second.mab_auth_type != MABMGR_MAB_PORT_AUTH_TYPE_DEF) && + (mabPortConfigCache.mab_auth_type != iter->second.mab_auth_type))) + { + if (L7_SUCCESS == mabPortMABAuthTypeSet(intIfNum, mabPortConfigCache.mab_auth_type)) + { + iter->second.mab_auth_type = mabPortConfigCache.mab_auth_type; + } + else + { + SWSS_LOG_ERROR("Unable to set MAB authentication type operationally."); + return false; + } + } + if (iter->second.mab_server_timeout != mabPortConfigCache.mab_server_timeout) + { + if (L7_SUCCESS == + mabPortMABServerTimeoutSet(intIfNum, mabPortConfigCache.mab_server_timeout)) + { + iter->second.mab_server_timeout = mabPortConfigCache.mab_server_timeout; + } + else + { + SWSS_LOG_ERROR("Unable to set MAB port server timeout."); + return false; + } + } + } + return true; +} + +bool MabMgr::doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum) +{ + SWSS_LOG_ENTER(); + const std::string & key = kfvKey(t); + mabPortConfigTableMap::iterator iter = m_mabPortConfigMap.find(key); + if(iter != m_mabPortConfigMap.end()) + { + if (iter->second.mab_enable != MABMGR_MAB_PORT_ENABLE_DEF) + { + if (L7_SUCCESS == mabPortMABEnableSet(intIfNum, MABMGR_MAB_PORT_ENABLE_DEF)) + { + iter->second.mab_enable = MABMGR_MAB_PORT_ENABLE_DEF; + } + else + { + SWSS_LOG_ERROR("Unable to set MAB enable with default."); + return false; + } + } + if (iter->second.mab_auth_type != MABMGR_MAB_PORT_AUTH_TYPE_DEF) + { + if (L7_SUCCESS == mabPortMABAuthTypeSet(intIfNum, MABMGR_MAB_PORT_AUTH_TYPE_DEF)) + { + iter->second.mab_auth_type = MABMGR_MAB_PORT_AUTH_TYPE_DEF; + } + else + { + SWSS_LOG_ERROR("Unable to set MAB authentication type with default."); + return false; + } + } + if (MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF != iter->second.mab_server_timeout) + { + if (L7_SUCCESS == + mabPortMABServerTimeoutSet(intIfNum, MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF)) + { + iter->second.mab_server_timeout = MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF; + } + else + { + SWSS_LOG_ERROR("Unable to set MAB port server timeout."); + return false; + } + } + } + return true; +} + +bool MabMgr::processMabConfigGlobalTblEvent(Selectable *tbl) +{ + SWSS_LOG_DEBUG("Received a table config event on MAB_GLOBAL_CONFIG_TABLE table"); + + std::deque entries; + m_confMabGlobalTbl.pops(entries); + + SWSS_LOG_DEBUG("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + // Check through all the data + for (auto entry : entries) + { + std::string key = kfvKey(entry); + std::string op = kfvOp(entry); + bool task_result = false; + + SWSS_LOG_DEBUG("Received %s as key and %s as OP", key.c_str(), op.c_str()); + + if (op == SET_COMMAND) + { + task_result = doMabGlobalTableSetTask(entry); + } + else if (op == DEL_COMMAND) + { + task_result = doMabGlobalTableDeleteTask(); + } + if (!task_result) + return false; + } + return true; +} + +bool MabMgr::doMabGlobalTableSetTask(const KeyOpFieldsValuesTuple & t) +{ + SWSS_LOG_ENTER(); + + // Update mabGlobalConfigCache with incoming table data + mabGlobalConfigCacheParams_t mabGlobalConfigCache; + mabGlobalConfigCache.group_size = MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF; + mabGlobalConfigCache.separator = MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF; + mabGlobalConfigCache.attrCase = MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF; + + for (auto item = kfvFieldsValues(t).begin(); item != kfvFieldsValues(t).end(); item++) + { + const std::string & field = fvField(*item); + const std::string & value = fvValue(*item); + + if (field == "group_size") + { + if(value == "1") + mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_1; + else if(value == "2") + mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_2; + else if(value == "4") + mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_4; + else if(value == "12") + mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_12; + else { + SWSS_LOG_WARN("Invalid option recieved for groupsize MAB request format attribute1: %s", value.c_str()); + continue; + } + } + if (field == "separator") + { + if(value == "-") + mabGlobalConfigCache.separator = L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_IETF; + else if(value == ":") + mabGlobalConfigCache.separator = L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_LEGACY; + else if(value == ".") + mabGlobalConfigCache.separator = L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_DOT; + else { + SWSS_LOG_WARN("Invalid option recieved for separator MAB request format attribute1: %s", value.c_str()); + continue; + } + } + if (field == "case") + { + if(value == "lowercase") + mabGlobalConfigCache.attrCase = L7_MAB_REQUEST_ATTRIBUTE1_CASE_LOWER; + else if(value == "uppercase") + mabGlobalConfigCache.attrCase = L7_MAB_REQUEST_ATTRIBUTE1_CASE_UPPER; + else { + SWSS_LOG_WARN("Invalid option recieved for case MAB request format attribute1: %s", value.c_str()); + continue; + } + } + } + + // Update MAB global config placeholder with table updates + // group_size + if (((mabGlobalConfigTable.group_size == MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF) && + (mabGlobalConfigCache.group_size != MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF)) || + ((mabGlobalConfigTable.group_size != MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF) && + (mabGlobalConfigCache.group_size != mabGlobalConfigTable.group_size))) + { + if (L7_SUCCESS == mabRequestFormatAttribut1GroupSizeSet(mabGlobalConfigCache.group_size)) + { + mabGlobalConfigTable.group_size = mabGlobalConfigCache.group_size; + } + else + { + SWSS_LOG_ERROR("Unable to set the groupsize for formatting the MAB attribute1."); + return false; + } + } + // separator + if (((mabGlobalConfigTable.separator == MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF) && + (mabGlobalConfigCache.separator != MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF)) || + ((mabGlobalConfigTable.separator != MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF) && + (mabGlobalConfigCache.separator != mabGlobalConfigTable.separator))) + { + if (L7_SUCCESS == mabRequestFormatAttribute1SeparatorSet(mabGlobalConfigCache.separator)) + { + mabGlobalConfigTable.separator = mabGlobalConfigCache.separator; + } + else + { + SWSS_LOG_ERROR("Unable to set the separator for formatting the MAB attribute1."); + return false; + } + } + // case + if (((mabGlobalConfigTable.attrCase == MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF) && + (mabGlobalConfigCache.attrCase != MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF)) || + ((mabGlobalConfigTable.attrCase != MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF) && + (mabGlobalConfigCache.attrCase != mabGlobalConfigTable.attrCase))) + { + if (L7_SUCCESS == mabRequestFormatAttribute1CaseSet(mabGlobalConfigCache.attrCase)) + { + mabGlobalConfigTable.attrCase = mabGlobalConfigCache.attrCase; + } + else + { + SWSS_LOG_ERROR("Unable to set the case for formatting the MAB attribute1."); + return false; + } + } + return true; +} + +bool MabMgr::doMabGlobalTableDeleteTask() +{ + SWSS_LOG_ENTER(); + + if (mabGlobalConfigTable.group_size != MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF) + { + if (L7_SUCCESS == mabRequestFormatAttribut1GroupSizeSet(MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF)) + { + mabGlobalConfigTable.group_size = MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF; + } + else + { + SWSS_LOG_ERROR("Unable to set groupsize with default for formatting the MAB attribute1."); + return false; + } + } + if (mabGlobalConfigTable.separator != MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF) + { + if (L7_SUCCESS == mabRequestFormatAttribute1SeparatorSet(MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF)) + { + mabGlobalConfigTable.separator = MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF; + } + else + { + SWSS_LOG_ERROR("Unable to set separator with default for formatting the MAB attribute1."); + return false; + } + } + if (mabGlobalConfigTable.attrCase != MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF) + { + if (L7_SUCCESS == mabRequestFormatAttribute1CaseSet(MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF)) + { + mabGlobalConfigTable.attrCase = MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF; + } + else + { + SWSS_LOG_ERROR("Unable to set case for formatting the MAB attribute1."); + return false; + } + } + return true; +} + +string execute(string command) { + char buffer[128]; + string result = ""; + + cout << "command is " << command << endl; + // Open pipe to file + FILE* pipe = popen(command.c_str(), "r"); + if (!pipe) { + return "popen failed!"; + } + + // read till end of process: + while (!feof(pipe)) { + + // use buffer to read and add to result + if (fgets(buffer, 128, pipe) != NULL) + result += buffer; + } + + pclose(pipe); + return result; +} + +void MabMgr::updateRadiusServerGlobalKey(string newKey, string oldKey) { + + SWSS_LOG_ENTER(); + bool update = false; + L7_RC_t rc = L7_FAILURE; + + if (0 == newKey.compare(oldKey)) + { + return; + } + + for (auto& item: m_radius_info.radius_auth_server_list) + { + /* server specific is configured */ + if (0 != item.second.server_key.size()) + { + continue; + } + + /* Check and update Radius server if using Global key */ + if (0 != newKey.size()) + { + item.second.server_update = true; + update = true; + } + else + { + rc = mabRadiusServerUpdate(RADIUS_MAB_SERVER_DELETE, "auth", + item.second.server_ip.c_str(), + item.second.server_priority.c_str(), + oldKey.c_str(), + item.second.server_port.c_str(), + item.second.server_vrf.c_str(), + item.second.server_source_intf.c_str()); + if (L7_SUCCESS != rc) + { + SWSS_LOG_ERROR("Unable to update radius server details for MAB ip = %s, port = %s, priority = %s", + item.second.server_ip.c_str(), + item.second.server_port.c_str(), + item.second.server_priority.c_str()); + } + } + } + + /* Due to global key change update server needed */ + if (true == update) + { + updateRadiusServer(); + } +} + +void MabMgr::updateRadiusServer() { + + SWSS_LOG_ENTER(); + L7_RC_t rc = L7_FAILURE; + struct addrinfo* result; + char ip[INET6_ADDRSTRLEN+1]; + void * src = NULL; + + SWSS_LOG_NOTICE("Deriving new RADIUS Servers for MAB"); + + for (auto& item: m_radius_info.radius_auth_server_list) + { + if (false == item.second.server_update) + { + SWSS_LOG_INFO("skipped %s as update not needed.", item.first.c_str()); + continue; + } + + if (getaddrinfo(item.first.c_str(), NULL, NULL, &result) || result == NULL) + { + SWSS_LOG_WARN("skipped %s as it could not resolve.", item.first.c_str()); + item.second.dns_ok = false; + continue; + } + + if(result->ai_family == AF_INET) + src = &((struct sockaddr_in*)result->ai_addr)->sin_addr; + else + src = &((struct sockaddr_in6*)result->ai_addr)->sin6_addr; + + inet_ntop(result->ai_family, src, ip, INET6_ADDRSTRLEN+1); + freeaddrinfo(result); + + //Check if radius server has key configured. If not, + // pick global key. If key does not exist, skip to next server. + if ((item.second.server_key == "") && (m_radius_info.m_radiusGlobalKey == "")) + { + SWSS_LOG_WARN("skipped %s as no key is configured.", item.first.c_str()); + continue; + } + + string newKey = m_radius_info.m_radiusGlobalKey; + if (item.second.server_key != "") + { + newKey = item.second.server_key; + } + + string radiusIp(ip); + item.second.server_ip = radiusIp; + + rc = mabRadiusServerUpdate(RADIUS_MAB_SERVER_ADD, "auth", item.second.server_ip.c_str(), + item.second.server_priority.c_str(), + newKey.c_str(), + item.second.server_port.c_str(), + item.second.server_vrf.c_str(), + item.second.server_source_intf.c_str()); + if (L7_SUCCESS != rc) + { + SWSS_LOG_ERROR("Radius server update - Unable to update radius server details for MAB."); + return; + } + SWSS_LOG_NOTICE("Updating radius details for MAB ip = %s, port = %s, priority = %s", + item.second.server_ip.c_str(), + item.second.server_port.c_str(), + item.second.server_priority.c_str()); + item.second.server_update = false; + item.second.dns_ok = true; + } + return; +} + +void MabMgr::updateRadiusGlobalInfo() { + L7_RC_t rc = L7_FAILURE; + string nas_ip(""); + string nas_id(""); + + if (m_radius_info.nas_ip.size()) + { + nas_ip = m_radius_info.nas_ip; + nas_id = m_radius_info.nas_ip; + } + else if (m_radius_info.mgmt_ip.size()) + { + nas_ip = m_radius_info.mgmt_ip; + nas_id = m_radius_info.mgmt_ip; + } + else if (m_radius_info.mgmt_ipv6.size()) + { + nas_ip = m_radius_info.mgmt_ipv6; + nas_id = m_radius_info.mgmt_ipv6; + } + + if (nas_ip.size() && nas_id.size()) + { + rc = mabRadiusGlobalCfgUpdate(nas_ip.c_str(), nas_id.c_str()); + if (L7_SUCCESS != rc) + { + SWSS_LOG_ERROR("Unable to update radius global configuration nas ip = %s, nas_id = %s", + nas_ip.c_str(), nas_id.c_str()); + } + } + return; +} + +void MabMgr::reloadRadiusServers() +{ + SWSS_LOG_ENTER(); + L7_RC_t rc = L7_FAILURE; + bool server_update = false; + + SWSS_LOG_NOTICE("Reloading RADIUS Servers for MAB"); + + /*Check for servers that failed DNS resolution */ + for (auto& item: m_radius_info.radius_auth_server_list) + { + if (false == item.second.dns_ok) + { + item.second.server_update = true; + server_update = true; + } + } + + if (true == server_update) + { + SWSS_LOG_NOTICE("Reloading DNS failed RADIUS Servers for MAB"); + updateRadiusServer(); + } + + rc = mabRadiusServerUpdate(RADIUS_MAB_SERVERS_RELOAD, "auth", + NULL, NULL, NULL, NULL, NULL, NULL); + + if (L7_SUCCESS != rc) + { + SWSS_LOG_ERROR("RADIUS Servers reload - Unable to reload."); + } + + return; +} + +bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) +{ + SWSS_LOG_ENTER(); + SWSS_LOG_NOTICE("Received a RADIUS_SERVER event"); + + deque entries; + m_confRadiusServerTable.pops(entries); + + SWSS_LOG_NOTICE("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + // Check through all the data + for (auto entry : entries) + { + string key = kfvKey(entry); + string val = kfvOp(entry); + string cmd(""); + + SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); + + if (val == SET_COMMAND) + { + SWSS_LOG_NOTICE("SET operation on RADIUS_SERVER table"); + + m_radius_info.radius_auth_server_list[key].server_port = ""; + m_radius_info.radius_auth_server_list[key].server_key = ""; + m_radius_info.radius_auth_server_list[key].server_priority = ""; + m_radius_info.radius_auth_server_list[key].server_vrf = ""; + m_radius_info.radius_auth_server_list[key].server_source_intf = ""; + m_radius_info.radius_auth_server_list[key].server_update = true; + m_radius_info.radius_auth_server_list[key].dns_ok = true; + + // Look at the data that is sent for this key + + for (auto i : kfvFieldsValues(entry)) + { + string a = fvField(i); + string b = fvValue(i); + + SWSS_LOG_DEBUG("Received %s as field and %s as value", a.c_str(), b.c_str()); + + if (a == "passkey") + { + DBus::Struct > ret; + ret = HostQuery_keyctl("pwDecrypt", b.c_str()); + if (0 != ret._1) + { + SWSS_LOG_ERROR("RADIUS server key is not decrypted properly and hence the MAB service is not steady."); + return false; + } + m_radius_info.radius_auth_server_list[key].server_key = ret._2; + } + else if (a == "auth_port") + { + m_radius_info.radius_auth_server_list[key].server_port = b; + } + else if (a == "priority") + { + m_radius_info.radius_auth_server_list[key].server_priority = b; + } + else if (a == "vrf") + { + m_radius_info.radius_auth_server_list[key].server_vrf = b; + } + else if (a == "src_intf") + { + m_radius_info.radius_auth_server_list[key].server_source_intf = b; + } + } + updateRadiusServer(); + } + else if (val == DEL_COMMAND) + { + L7_RC_t rc = L7_FAILURE; + SWSS_LOG_INFO("Delete Radius server for MAB %s ", + m_radius_info.radius_auth_server_list[key].server_ip.c_str()); + // server deleted + rc = mabRadiusServerUpdate(RADIUS_MAB_SERVER_DELETE, "auth", + m_radius_info.radius_auth_server_list[key].server_ip.c_str(), + m_radius_info.radius_auth_server_list[key].server_priority.c_str(), + m_radius_info.radius_auth_server_list[key].server_key.c_str(), + m_radius_info.radius_auth_server_list[key].server_port.c_str(), + m_radius_info.radius_auth_server_list[key].server_vrf.c_str(), + m_radius_info.radius_auth_server_list[key].server_source_intf.c_str()); + if (rc != L7_SUCCESS) + { + SWSS_LOG_ERROR("Radius server delete - Unable to delete radius server details for MAB."); + } + m_radius_info.radius_auth_server_list.erase(key); + } + } + + return true; +} + +bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) +{ + SWSS_LOG_ENTER(); + SWSS_LOG_NOTICE("Received a RADIUS event"); + string tmp_radiusGlobalKey(m_radius_info.m_radiusGlobalKey); + string tmp_nas_ip(m_radius_info.nas_ip); + + deque entries; + m_confRadiusGlobalTable.pops(entries); + + SWSS_LOG_NOTICE("Received %d entries", (int) entries.size()); + + /* Nothing popped */ + if (entries.empty()) + { + return false; + } + + // Check through all the data + for (auto entry : entries) + { + string key = kfvKey(entry); + string val = kfvOp(entry); + string cmd(""); + + SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); + + // Removal of radius key and nas_ip as these are also sent as a SET + m_radius_info.m_radiusGlobalKey = ""; + m_radius_info.nas_ip = ""; + + if (val == SET_COMMAND) + { + SWSS_LOG_NOTICE("SET operation on RADIUS table"); + + // Look at the data that is sent for this key + for (auto i : kfvFieldsValues(entry)) + { + + string a = fvField(i); + string b = fvValue(i); + + SWSS_LOG_DEBUG("Received %s as field and %s as value", a.c_str(), b.c_str()); + + if (a == "passkey") + { + DBus::Struct > ret; + ret = HostQuery_keyctl("pwDecrypt", b.c_str()); + if (0 != ret._1) + { + SWSS_LOG_ERROR("RADIUS server key is not decrypted properly and hence the MAB service is not steady."); + return false; + } + m_radius_info.m_radiusGlobalKey = ret._2; + } + else if (a == "nas_ip") + { + m_radius_info.nas_ip = b; + } + } + } + else if (val == DEL_COMMAND) + { + m_radius_info.m_radiusGlobalKey = ""; + m_radius_info.nas_ip = ""; + } + } + + updateRadiusServerGlobalKey(m_radius_info.m_radiusGlobalKey, tmp_radiusGlobalKey); + + if (m_radius_info.nas_ip != tmp_nas_ip) + { + updateRadiusGlobalInfo(); + } + + return true; +} + +bool MabMgr::processMgmtIntfTblEvent(Selectable *tbl) +{ + std::deque entries; + m_mgmtIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on MGMT_INTERFACE Table", (int) entries.size()); + + // Removal of MGMT IP also is sent as a SET + m_radius_info.mgmt_ip = ""; + m_radius_info.mgmt_ipv6 = ""; + + for (auto entry : entries) + { + std::string key = kfvKey(entry); + SWSS_LOG_NOTICE("key %s", key.c_str()); + + auto tokens = tokenize(key, ':'); + SWSS_LOG_NOTICE("size %d", tokens.size()); + + // pick only IPv4 address of the management interface + if (2 == tokens.size()) + { + // eth0:a.b.c.d/mask + auto tokens1 = tokenize(tokens[1], '/'); + SWSS_LOG_NOTICE("Management IPv4 %s", tokens1[0].c_str()); + m_radius_info.mgmt_ip = tokens1[0]; + } + else if (tokens.size() > 2) + { + // eth0:2001::64/mask. Remove "eth0:" + string ipv6Str = key.substr(5); + + auto tokens1 = tokenize(ipv6Str, '/'); + SWSS_LOG_NOTICE("Management IPv6 %s", tokens1[0].c_str()); + m_radius_info.mgmt_ipv6 = tokens1[0]; + } + } + + string mgmt_intf("eth0"); + + if (0 == m_radius_info.nas_ip.size()) + { + SWSS_LOG_NOTICE("Interface %s address update for nas ip.", mgmt_intf.c_str()); + updateRadiusGlobalInfo(); + } + + reloadRadiusServers(); + + return true; +} + +bool MabMgr::IsSourceIntf(const string interface) +{ + for (auto& item: m_radius_info.radius_auth_server_list) + { + if (item.second.server_source_intf == interface) + { + return true; + } + } + return false; +} + +bool MabMgr::processIntfTblEvent(Selectable *tbl) +{ + std::deque entries; + + if (tbl == ((Selectable *) & m_IntfTbl)) + { + m_IntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on INTERFACE Table", (int) entries.size()); + } + else if (tbl == ((Selectable *) & m_VlanIntfTbl)) + { + m_VlanIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on VLAN_INTERFACE Table", (int) entries.size()); + } + else if (tbl == ((Selectable *) & m_LoIntfTbl)) + { + m_LoIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on LOOPBACK_INTERFACE Table", (int) entries.size()); + } + else if (tbl == ((Selectable *) & m_PoIntfTbl)) + { + m_PoIntfTbl.pops(entries); + SWSS_LOG_NOTICE("Received %d entries from config event on PORTCHANNEL_INTERFACE Table", (int) entries.size()); + } + + for (auto entry : entries) + { + std::string key = kfvKey(entry); + SWSS_LOG_NOTICE("key %s", key.c_str()); + + auto key_tokens = tokenize(key, '|'); + SWSS_LOG_NOTICE("size %d", key_tokens.size()); + + if (2 == key_tokens.size()) + { + // Ethernet0|IPAddress + if (IsSourceIntf(key_tokens[0])) + { + auto ip_tokens = tokenize(key_tokens[1], '/'); + SWSS_LOG_NOTICE("Interface %s used as Source Interface. Address %s/%s", + key_tokens[0].c_str(), ip_tokens[0].c_str(), ip_tokens[1].c_str()); + reloadRadiusServers(); + break; + } + } + } + + return true; +} + diff --git a/mabmgr/mabmgr.h b/mabmgr/mabmgr.h new file mode 100644 index 0000000..34288b6 --- /dev/null +++ b/mabmgr/mabmgr.h @@ -0,0 +1,135 @@ +/* + * Copyright 2019 Broadcom Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MABMGR_H_ +#define _MABMGR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "redisapi.h" +#include "auth_mgr_exports.h" +#include "mab_exports.h" + +typedef struct radius_server_info_s { + std::string server_port; + std::string server_key; + std::string server_ip; + std::string server_priority; + std::string server_vrf; + std::string server_source_intf; + bool server_update; + bool dns_ok; +}radius_server_info_t; + +typedef std::map radius_server_info_map_t; + +typedef struct radius_info_s { + string m_radiusGlobalKey; + std::string nas_ip; + std::string mgmt_ip; + std::string mgmt_ipv6; + radius_server_info_map_t radius_auth_server_list; + radius_server_info_map_t radius_acct_server_list; +}radius_info_t; + +#define MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_2 +#define MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_LEGACY +#define MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF L7_MAB_REQUEST_ATTRIBUTE1_CASE_UPPER +#define MABMGR_MAB_PORT_ENABLE_DEF L7_DISABLE +#define MABMGR_MAB_PORT_AUTH_TYPE_DEF L7_AUTHMGR_PORT_MAB_AUTH_TYPE_EAP_MD5 +#define MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF FD_MAB_PORT_SERVER_TIMEOUT + +/* MAB GLOBAL config table param cache Info */ +typedef struct { + L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_t group_size; + L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_t separator; + L7_MAB_REQUEST_ATTRIBUTE1_CASE_t attrCase; +} mabGlobalConfigCacheParams_t; + +/* MAB port config table param cache Info */ +typedef struct mabPortConfigCacheParams_t { + bool mab_enable; + L7_AUTHMGR_PORT_MAB_AUTH_TYPE_t mab_auth_type; + L7_uint32 mab_server_timeout; +} mabPortConfigCacheParams_t; + +/* MAP to store MAB port config table params, + * Key is "interface-id" (Eg. Ethernet0) + * Value is "mabPortConfigCacheParams_t" + */ +typedef std::map mabPortConfigTableMap; + +using namespace swss; +using namespace std; + +class MabMgr +{ +public: + MabMgr(DBConnector *configDb, DBConnector *stateDb, DBConnector *appDb); + std::vector getSelectables(); + bool processDbEvent(Selectable *source); + + /* Placeholder for MAB Global table config params */ + static mabGlobalConfigCacheParams_t mabGlobalConfigTable; + + /* Debug routine. */ + void showDebugInfo(DebugShCmd *cmd); + +private: + //tables this component listens to + SubscriberStateTable m_confMabPortTbl; + SubscriberStateTable m_confMabGlobalTbl; + SubscriberStateTable m_confRadiusServerTable; + SubscriberStateTable m_confRadiusGlobalTable; + SubscriberStateTable m_mgmtIntfTbl; + SubscriberStateTable m_IntfTbl; + SubscriberStateTable m_VlanIntfTbl; + SubscriberStateTable m_LoIntfTbl; + SubscriberStateTable m_PoIntfTbl; + + radius_info_t m_radius_info; + mabPortConfigTableMap m_mabPortConfigMap; + + // DB Event handler functions + bool processMabConfigPortTblEvent(Selectable *tbl); + bool processMabConfigGlobalTblEvent(Selectable *tbl); + bool processRadiusServerTblEvent(Selectable *tbl); + bool processRadiusGlobalTblEvent(Selectable *tbl); + bool processMgmtIntfTblEvent(Selectable *tbl); + bool processIntfTblEvent(Selectable *tbl); + bool doMabGlobalTableSetTask(const KeyOpFieldsValuesTuple & t); + bool doMabGlobalTableDeleteTask(); + bool doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum); + bool doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum); + + void updateRadiusServer(); + void updateRadiusServerGlobalKey(string newKey, string oldKey); + void updateRadiusGlobalInfo(); + bool IsSourceIntf(const string interface); + void reloadRadiusServers() ; +}; + +#endif // _MABMGR_H_ diff --git a/mabmgr/mabmgr_main.cpp b/mabmgr/mabmgr_main.cpp new file mode 100644 index 0000000..7bb5ea1 --- /dev/null +++ b/mabmgr/mabmgr_main.cpp @@ -0,0 +1,110 @@ +/* + * Copyright 2019 Broadcom Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include "datatypes.h" +#include "osapi.h" +#include "mabmgr.h" +#include "mab_include.h" +#include +#include "fpinfra.h" + +int main(int argc, char *argv[]) +{ + cout<<"Invoking fpinfraInit" << endl; + fpinfraInit(); + + if (mabInit () != L7_SUCCESS) + cout<<"Fail" << endl; + else + cout<<"Success linked" << endl; + + if (osapiWaitForTaskInit (L7_MAB_DB_TASK_SYNC, L7_WAIT_FOREVER) != + L7_SUCCESS) + { + return -1; + } + + cout<<"DB_TASK_SYNC Success" << endl; + + /* Set log level MSG_DEBUG to get hostapd logs for debugging purposes + * Use the below values from wpa_debug.h + * enum { MSG_EXCESSIVE, MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; + */ + mab_radius_server_debug_level_set(2 /*MSG_DEBUG*/); + + try + { + SWSS_LOG_NOTICE("-----Starting MabMgr-----"); + sleep(20); + swss::DBConnector stateDb("STATE_DB", 0); + swss::DBConnector configDb("CONFIG_DB", 0); + swss::DBConnector appDb("APPL_DB", 0); + swss::DBConnector log_db(LOGLEVEL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + + MabMgr mab(&configDb, &stateDb, &appDb); + DebugShCmdHandler dbg_hdlr(&log_db, "MABMGRD"); + + // App Marking closest UP status + Table feat_tbl(&stateDb, STATE_FEATURE_TABLE_NAME); + std::vector attrs; + FieldValueTuple up_ready_status("UP_STATUS", "True"); + FieldValueTuple fail_reason("FAIL_REASON", ""); + char buffer[100]; + std::time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = gmtime(&rawtime); + strftime(buffer, 100, "%Y-%m-%d %H:%M:%S", timeinfo); + FieldValueTuple time("TIME", string(buffer)); + attrs.push_back(up_ready_status); + attrs.push_back(fail_reason); + attrs.push_back(time); + feat_tbl.set("mabd", attrs); + SWSS_LOG_NOTICE("mabd marked its UP Status to True"); + + //register for the table events + swss::Select s; + s.addSelectables(mab.getSelectables()); + s.addSelectables(dbg_hdlr.getSelectables()); + + //wait for the events and process them + while (true) + { + SWSS_LOG_NOTICE("Waiting for MAB Table Events"); + + swss::Selectable *sel = NULL; + s.select(&sel); + + if (dbg_hdlr.isDebugSelectable(sel)) + { + dbg_hdlr.process(sel); + } + else + { + //Pass on the processing to the Mab Manager + mab.processDbEvent(sel); + } + } + + } + catch (const exception &e) + { + SWSS_LOG_ERROR("Runtime error: %s", e.what()); + } + return -1; +} From 82685e725a8bcb4960cfa5a43634a88f1412fbb5 Mon Sep 17 00:00:00 2001 From: Amitabha Sen Date: Tue, 10 Oct 2023 01:53:24 -0700 Subject: [PATCH 2/2] Initial support for MABMgr and HostapdMgr --- hostapdmgr/hostapdmgr.cpp | 402 +------------------------ hostapdmgr/hostapdmgr.h | 25 -- hostapdmgr/hostapdmgr_main.cpp | 20 +- mabmgr/mabmgr.cpp | 521 ++------------------------------- mabmgr/mabmgr.h | 47 +-- mabmgr/mabmgr_main.cpp | 20 +- 6 files changed, 49 insertions(+), 986 deletions(-) diff --git a/hostapdmgr/hostapdmgr.cpp b/hostapdmgr/hostapdmgr.cpp index a05f912..eb6d618 100644 --- a/hostapdmgr/hostapdmgr.cpp +++ b/hostapdmgr/hostapdmgr.cpp @@ -34,49 +34,17 @@ #include "tokenize.h" #define TEAM_DRV_NAME "team" -#define HOSTAPD_CMD_BUFFSZ 2048 -const string MGMT_PREFIX = "eth"; const string INTFS_PREFIX = "E"; -const string LAG_PREFIX = "PortChannel"; - const string HOSTAPD_PID_FILE = "/etc/hostapd/hostapdPid"; -const string HOSTAPD_SERVER_TIMEOUT = "serverTimeout"; -const string HOSTAPD_QUIET_PERIOD = "quietPeriod"; HostapdMgr *hostapd; -DEBUGSH_CLI(HostapdMgrRadiusStats, - "show system internal hostapdmgr radius-stats ETHERNETNAME", - SHOW_COMMAND, - SYSTEM_DEBUG_COMMAND, - INTERNAL_COMMAND, - "HostapdMgr related commands", - "Radius stats", - "Interface") -{ - string intf = ""; - - if (args.size() == 0) - { - return; - } - - intf = args[0]; - - hostapd->showDebugInfo(this, intf); -} - HostapdMgr::HostapdMgr(DBConnector *configDb, DBConnector *appDb) : m_confHostapdPortTbl(configDb, CFG_PAC_PORT_CONFIG_TABLE), m_confHostapdGlobalTbl(configDb, CFG_PAC_HOSTAPD_GLOBAL_CONFIG_TABLE), m_confRadiusServerTable(configDb, "RADIUS_SERVER"), - m_confRadiusGlobalTable(configDb, "RADIUS"), - m_mgmtIntfTbl(appDb, "MGMT_INTF_TABLE"), - m_IntfTbl(configDb, CFG_INTF_TABLE_NAME), - m_VlanIntfTbl(configDb, CFG_VLAN_INTF_TABLE_NAME), - m_LoIntfTbl(configDb, CFG_LOOPBACK_INTERFACE_TABLE_NAME), - m_PoIntfTbl(configDb, CFG_LAG_INTF_TABLE_NAME) + m_confRadiusGlobalTable(configDb, "RADIUS") { Logger::linkToDbNative("hostapdmgr"); @@ -86,41 +54,6 @@ HostapdMgr::HostapdMgr(DBConnector *configDb, DBConnector *appDb) : stop_hostapd = false; hostapd = this; - SWSS_LOG_DEBUG("Installing HostapdMgr commands"); - DebugShCmd::install(new HostapdMgrRadiusStats()); -} - -void HostapdMgr::showDebugInfo(DebugShCmd *cmd, string intf) -{ - string cmdstr = "hostapd_cli -i " + intf + " mib"; - array buffer; - FILE* pipe = popen(cmdstr.c_str(), "r"); - string output; - - if (pipe) { - - DEBUGSH_OUT(cmd, "Dumping Hostapdmgr radius stats\n\n"); - DEBUGSH_OUT(cmd, "==============================================\n"); - - while (!feof(pipe)) { - if (fgets(buffer.data(), HOSTAPD_CMD_BUFFSZ, pipe) != NULL) { - output.clear(); - output += buffer.data(); - - DEBUGSH_OUT(cmd, "%s", output.c_str()); - } - } - - DEBUGSH_OUT(cmd, "\n==============================================\n\n"); - - if (0 != pclose(pipe)) { - DEBUGSH_OUT(cmd, "dot1x not enabled or HOSTAPD not running.\n"); - } - } - else - { - DEBUGSH_OUT(cmd, "dot1x not enabled or HOSTAPD not running.\n"); - } } string HostapdMgr::getStdIfFormat(string key) @@ -135,8 +68,7 @@ string HostapdMgr::getStdIfFormat(string key) } vector HostapdMgr::getSelectables() { - vector selectables{ &m_confHostapdPortTbl, &m_confHostapdGlobalTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable, - &m_mgmtIntfTbl, &m_IntfTbl, &m_VlanIntfTbl, &m_PoIntfTbl, &m_LoIntfTbl }; + vector selectables{ &m_confHostapdPortTbl, &m_confHostapdGlobalTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable}; return selectables; } @@ -163,17 +95,6 @@ bool HostapdMgr::processDbEvent(Selectable *tbl) { return processRadiusGlobalTblEvent(tbl); } - if (tbl == ((Selectable *) & m_mgmtIntfTbl)) { - return processMgmtIntfTblEvent(tbl); - } - - if ((tbl == ((Selectable *) & m_IntfTbl)) || - (tbl == ((Selectable *) & m_VlanIntfTbl)) || - (tbl == ((Selectable *) & m_LoIntfTbl)) || - (tbl == ((Selectable *) & m_PoIntfTbl))) { - return processIntfTblEvent(tbl); - } - SWSS_LOG_DEBUG("Received event UNKNOWN to HOSTAPD, ignoring "); return false; } @@ -211,10 +132,6 @@ bool HostapdMgr::processHostapdConfigPortTblEvent(Selectable *tbl) hostapd_intf_info_t intf; intf.control_mode = "force-authorized"; intf.capabilities = "none"; - intf.quiet_period = PAC_QUIET_PERIOD_DEF; - intf.server_timeout = PAC_SERVER_TIMEOUT_DEF; - intf.server_timeout_modified = false; - intf.quiet_period_modified = false; intf.admin_status = 0; intf.link_status = 0; intf.config_created = false; @@ -230,7 +147,8 @@ bool HostapdMgr::processHostapdConfigPortTblEvent(Selectable *tbl) { SWSS_LOG_NOTICE("m_radius_info.radius_auth_server_list.size() is non-zero "); } - if (val == SET_COMMAND) + + if (val == SET_COMMAND) { vector new_interfaces; vector del_interfaces; @@ -303,22 +221,11 @@ bool HostapdMgr::processHostapdConfigPortTblEvent(Selectable *tbl) } m_intf_info[key].control_mode = b; } - else if ((a == "server_timeout") && (m_intf_info[key].server_timeout != (unsigned int)stoi(b))) - { - m_intf_info[key].server_timeout = (unsigned int)stoi(b); - m_intf_info[key].server_timeout_modified = true; - } - else if ((a == "quiet_period") && (m_intf_info[key].quiet_period != (unsigned int)stoi(b))) - { - m_intf_info[key].quiet_period = (unsigned int)stoi(b); - m_intf_info[key].quiet_period_modified = true; - } } /* update JSON for new_interfaces and del_interfaces */ informHostapd("new", new_interfaces); informHostapd("deleted", del_interfaces); - setPortDot1xTimeoutParams(); } else if (val == DEL_COMMAND) { @@ -346,7 +253,8 @@ bool HostapdMgr::processHostapdConfigGlobalTblEvent(Selectable *tbl) return false; } - SWSS_LOG_NOTICE("enable_auth %d: ", m_glbl_info.enable_auth); + SWSS_LOG_NOTICE("enable_auth %d: ", m_glbl_info.enable_auth); + // Check through all the data for (auto entry : entries) { @@ -397,8 +305,6 @@ bool HostapdMgr::processHostapdConfigGlobalTblEvent(Selectable *tbl) /* Update JSON */ informHostapd("new", interfaces); - setPortDot1xTimeoutParams(); - } } else if (b == "false") @@ -538,8 +444,6 @@ void HostapdMgr::updateRadiusServer() { m_radiusServerInUseInfo.server_port = item.second.server_port; m_radiusServerInUseInfo.server_key = m_radius_info.m_radiusGlobalKey; m_radiusServerInUseInfo.server_priority = item.second.server_priority; - m_radiusServerInUseInfo.server_vrf = item.second.server_vrf; - m_radiusServerInUseInfo.server_source_intf = item.second.server_source_intf; if (item.second.server_key != "") { m_radiusServerInUseInfo.server_key = item.second.server_key; @@ -567,7 +471,6 @@ void HostapdMgr::updateRadiusServer() { /* update JSON file */ informHostapd("modified", interfaces); - setPortDot1xTimeoutParams(); return; } @@ -624,8 +527,6 @@ bool HostapdMgr::processRadiusServerTblEvent(Selectable *tbl) { m_radius_info.radius_auth_server_list[key].server_port = ""; m_radius_info.radius_auth_server_list[key].server_key = ""; m_radius_info.radius_auth_server_list[key].server_priority = ""; - m_radius_info.radius_auth_server_list[key].server_vrf = ""; - m_radius_info.radius_auth_server_list[key].server_source_intf = ""; // Look at the data that is sent for this key for (auto i : kfvFieldsValues(entry)) @@ -654,14 +555,6 @@ bool HostapdMgr::processRadiusServerTblEvent(Selectable *tbl) { { m_radius_info.radius_auth_server_list[key].server_priority = b; } - else if (a == "vrf") - { - m_radius_info.radius_auth_server_list[key].server_vrf = b; - } - else if (a == "src_intf") - { - m_radius_info.radius_auth_server_list[key].server_source_intf = b; - } } } else if (val == DEL_COMMAND) @@ -684,7 +577,6 @@ bool HostapdMgr::processRadiusGlobalTblEvent(Selectable *tbl) { SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("Received a RADIUS table event"); string key(m_radius_info.m_radiusGlobalKey); - string nas_ip(m_radius_info.nas_ip); deque entries; m_confRadiusGlobalTable.pops(entries); @@ -708,7 +600,6 @@ bool HostapdMgr::processRadiusGlobalTblEvent(Selectable *tbl) { // Incoming field values will not have passkey or nas_ip. Hence, we intiialize to NULL // so that incoming data will decide the final value. m_radius_info.m_radiusGlobalKey = ""; - m_radius_info.nas_ip = ""; SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); @@ -734,10 +625,6 @@ bool HostapdMgr::processRadiusGlobalTblEvent(Selectable *tbl) { m_radius_info.m_radiusGlobalKey = ret._2; } - else if (a == "nas_ip") - { - m_radius_info.nas_ip = b; - } } } else if (val == DEL_COMMAND) @@ -745,13 +632,12 @@ bool HostapdMgr::processRadiusGlobalTblEvent(Selectable *tbl) { SWSS_LOG_WARN("DEL operation on RADIUS table"); m_radius_info.m_radiusGlobalKey = ""; - m_radius_info.nas_ip = ""; } } // Since RADIUS config has been modified, deduce the new // RADIUS server to be used and inform hostapd if required. - if ((m_radius_info.m_radiusGlobalKey != key) || (m_radius_info.nas_ip != nas_ip)) + if (m_radius_info.m_radiusGlobalKey != key) { updateRadiusServer(); } @@ -759,117 +645,6 @@ bool HostapdMgr::processRadiusGlobalTblEvent(Selectable *tbl) { return true; } -bool HostapdMgr::processMgmtIntfTblEvent(Selectable *tbl) -{ - std::deque entries; - m_mgmtIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on MGMT_INTERFACE Table", (int) entries.size()); - - // Removal of MGMT IP also is sent as a SET - m_radius_info.mgmt_ip = ""; - m_radius_info.mgmt_ipv6 = ""; - - for (auto entry : entries) - { - std::string key = kfvKey(entry); - SWSS_LOG_NOTICE("key %s", key.c_str()); - - auto tokens = tokenize(key, ':'); - SWSS_LOG_NOTICE("size %d", tokens.size()); - - // pick only IPv4 address of the management interface - if (2 == tokens.size()) - { - // eth0:a.b.c.d/mask - auto tokens1 = tokenize(tokens[1], '/'); - SWSS_LOG_NOTICE("Management IPv4 %s", tokens1[0].c_str()); - m_radius_info.mgmt_ip = tokens1[0]; - } - else if (tokens.size() > 2) - { - // eth0:2001::64/mask. Remove "eth0:" - string ipv6Str = key.substr(5); - - auto tokens1 = tokenize(ipv6Str, '/'); - SWSS_LOG_NOTICE("Management IPv6 %s", tokens1[0].c_str()); - m_radius_info.mgmt_ipv6 = tokens1[0]; - } - } - - string mgmt_intf("eth0"); - - if ((0 == m_radius_info.nas_ip.size()) || - (IsSourceIntf(mgmt_intf))) - { - SWSS_LOG_NOTICE("Interface %s address update.", mgmt_intf.c_str()); - updateRadiusServer(); - } - - return true; -} - -bool HostapdMgr::IsSourceIntf(const string interface) -{ - for (auto& item: m_radius_info.radius_auth_server_list) - { - if (item.second.server_source_intf == interface) - { - return true; - } - } - return false; -} - -bool HostapdMgr::processIntfTblEvent(Selectable *tbl) -{ - std::deque entries; - - if (tbl == ((Selectable *) & m_IntfTbl)) - { - m_IntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on INTERFACE Table", (int) entries.size()); - } - else if (tbl == ((Selectable *) & m_VlanIntfTbl)) - { - m_VlanIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on VLAN_INTERFACE Table", (int) entries.size()); - } - else if (tbl == ((Selectable *) & m_LoIntfTbl)) - { - m_LoIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on LOOPBACK_INTERFACE Table", (int) entries.size()); - } - else if (tbl == ((Selectable *) & m_PoIntfTbl)) - { - m_PoIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on PORTCHANNEL_INTERFACE Table", (int) entries.size()); - } - - for (auto entry : entries) - { - std::string key = kfvKey(entry); - SWSS_LOG_NOTICE("key %s", key.c_str()); - - auto key_tokens = tokenize(key, '|'); - SWSS_LOG_NOTICE("size %d", key_tokens.size()); - - if (2 == key_tokens.size()) - { - // Ethernet0|IPAddress - if (IsSourceIntf(key_tokens[0])) - { - auto ip_tokens = tokenize(key_tokens[1], '/'); - SWSS_LOG_NOTICE("Interface %s used as Source Interface. Address %s/%s", - key_tokens[0].c_str(), ip_tokens[0].c_str(), ip_tokens[1].c_str()); - updateRadiusServer(); - break; - } - } - } - - return true; -} - void HostapdMgr::onMsg(int nlmsg_type, struct nl_object *obj) { @@ -1006,7 +781,6 @@ void HostapdMgr::onMsg(int nlmsg_type, struct nl_object *obj) /* update JSON file */ informHostapd("new", interfaces); - setPortDot1xTimeoutParams(); } /* down't bring down hostapd interface when admin state goes down. * it will get deleted with RTM_DELLINK. @@ -1036,42 +810,6 @@ void HostapdMgr::delPort(const string & alias) m_intf_info.erase(alias); } -void HostapdMgr::setPortDot1xTimeoutParams() -{ - SWSS_LOG_ENTER(); - if (0 == active_intf_cnt) - { - return; - } - - pid_t pid = getHostapdPid(); - - if (0 == pid) - { - return; - } - for (auto& item: m_intf_info) - { - if (true == item.second.config_created) - { - if ((true == item.second.server_timeout_modified) || - (PAC_SERVER_TIMEOUT_DEF != item.second.server_timeout)) - { - std::string s = std::to_string(item.second.server_timeout); - hostapdDot1xWpaEventSend(item.first, HOSTAPD_SERVER_TIMEOUT, s); - item.second.server_timeout_modified = false; - } - if ((true == item.second.quiet_period_modified) || - (PAC_QUIET_PERIOD_DEF != item.second.quiet_period)) - { - std::string s = std::to_string(item.second.quiet_period); - hostapdDot1xWpaEventSend(item.first, HOSTAPD_QUIET_PERIOD, s); - item.second.quiet_period_modified = false; - } - } - } -} - static bool file_exists(const string& file_name) { ifstream ifile; @@ -1368,33 +1106,6 @@ void HostapdMgr::createConfFile(const string& intf) content += "ctrl_interface=/var/run/hostapd\n"; content += "use_pae_group_addr=0\n"; - string nas_ip(""); - string nas_id(""); - - if (m_radius_info.nas_ip.size()) - { - nas_ip = m_radius_info.nas_ip; - nas_id = m_radius_info.nas_ip; - } - else if (m_radius_info.mgmt_ip.size()) - { - nas_ip = m_radius_info.mgmt_ip; - nas_id = m_radius_info.mgmt_ip; - } - else if (m_radius_info.mgmt_ipv6.size()) - { - nas_ip = m_radius_info.mgmt_ipv6; - nas_id = m_radius_info.mgmt_ipv6; - } - - if (nas_ip.size() && nas_id.size()) - { - content += "own_ip_addr="; - content += (nas_ip + "\n"); - content += "nas_identifier="; - content += (nas_id + "\n"); - } - vector> auth_sortedMap; for (auto& item: m_radius_info.radius_auth_server_list) { @@ -1434,37 +1145,8 @@ void HostapdMgr::createConfFile(const string& intf) content += (item.second.server_key + "\n"); } - if (item.second.server_vrf != "") - { - content += "auth_server_vrf="; - content += (item.second.server_vrf + "\n"); - } - - if (item.second.server_source_intf != "") - { - content += "auth_server_source_interface="; - content += (getHostIntfName(item.second.server_source_intf) + "\n"); - } - } - - vector> sortedMap; - for (auto& item: m_radius_info.radius_acct_server_list) - { - item.second.server_priority = (item.second.server_priority == "") ? - "0": item.second.server_priority; - sortedMap.push_back(item); - } - - for (auto const& item: sortedMap) - { - content += "acct_server_addr="; - content += (item.first + "\n"); - - content += "acct_server_port="; - content += (item.second.server_port + "\n"); - - content += "acct_server_shared_secret="; - content += (item.second.server_key + "\n"); + /* Write only the highest priroty server */ + break; } SWSS_LOG_NOTICE("active intf count %d ", active_intf_cnt); @@ -1625,69 +1307,3 @@ int HostapdMgr::waitForHostapdInit(pid_t hostapd_pid) return (pid == hostapd_pid)? 0 : -1; } -void HostapdMgr::hostapdDot1xWpaEventSend(const string& interface, const string& event, string& val) -{ - size_t len = 0; - char buf[128] = {'\0'}; - char cmd[128] = {'\0'}; - char bcast_addr[] = "FF:FF:FF:FF:FF:FF"; - string intf = getHostIntfName(interface); - - SWSS_LOG_DEBUG("Hostapd %s event %s = %s ", intf.c_str(), event.c_str(), val.c_str()); - snprintf(cmd, sizeof(cmd), "EAPOL_SET %s %s %s", bcast_addr, event.c_str(), val.c_str()); - - if (0 == hostapdWpaSyncSend(intf.c_str(), cmd, buf, &len)) - { - if (0 == strncmp("OK", buf, strlen("OK"))) - { - SWSS_LOG_INFO("Hostapd %s event %s = %s set successfully.", intf.c_str(), event.c_str(), val.c_str()); - return; - } - } - SWSS_LOG_WARN("Hostapd %s event %s = %s set failed.", intf.c_str(), event.c_str(), val.c_str()); -} - -int HostapdMgr::hostapdWpaSyncSend(const char *ctrl_ifname, const char * cmd, char *buf, size_t *len) -{ - static struct wpa_ctrl *ctrl_conn; - int ret; - char sock_file[128]; - - memset(sock_file, 0, sizeof(sock_file)); - sprintf(sock_file, "/var/run/hostapd/%s", ctrl_ifname); - - ctrl_conn = wpa_ctrl_open(sock_file); - if (NULL == ctrl_conn) - { - SWSS_LOG_NOTICE("Not connected to hostapd - command dropped.. retrying.."); - usleep(10 * 1000); - - ctrl_conn = wpa_ctrl_open(sock_file); - - if (NULL == ctrl_conn) - { - SWSS_LOG_NOTICE("Not connected to hostapd - command dropped..\n"); - return -1; - } - } - - *len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, len, NULL); - if (ret == -2) - { - SWSS_LOG_NOTICE("'%s' command timed out.\n", cmd); - return -2; - } - else if (ret < 0) - { - SWSS_LOG_NOTICE("'%s' command failed.\n", cmd); - return -1; - } - if (1) - { - buf[*len] = '\0'; - SWSS_LOG_NOTICE("hostapd reply %s", buf); - } - wpa_ctrl_close(ctrl_conn); - return 0; -} diff --git a/hostapdmgr/hostapdmgr.h b/hostapdmgr/hostapdmgr.h index b083079..c0cf2bd 100644 --- a/hostapdmgr/hostapdmgr.h +++ b/hostapdmgr/hostapdmgr.h @@ -36,10 +36,6 @@ using namespace swss; using namespace std; -#define REAUTH_PERIOD 3600 -#define PAC_SERVER_TIMEOUT_DEF 30 -#define PAC_QUIET_PERIOD_DEF 30 - void hostapdHandleDumpError(void *cbData); typedef struct hostapd_glbl_info_s { @@ -51,10 +47,6 @@ typedef struct hostapd_intf_info_s { std::string control_mode; unsigned int admin_status; unsigned int link_status; - unsigned int quiet_period = PAC_QUIET_PERIOD_DEF; - unsigned int server_timeout = PAC_SERVER_TIMEOUT_DEF; - bool server_timeout_modified = false; - bool quiet_period_modified = false; bool config_created; }hostapd_intf_info_t; @@ -63,8 +55,6 @@ typedef struct radius_server_info_s { std::string server_key; std::string server_priority; std::string server_ip; - std::string server_vrf; - std::string server_source_intf; bool config_ok; }radius_server_info_t; @@ -72,11 +62,7 @@ typedef std::map radius_server_info_map_t; typedef struct radius_info_s { string m_radiusGlobalKey; - std::string nas_ip; - std::string mgmt_ip; - std::string mgmt_ipv6; radius_server_info_map_t radius_auth_server_list; - radius_server_info_map_t radius_acct_server_list; }radius_info_t; typedef std::map hostapd_intf_info_map_t; @@ -98,11 +84,6 @@ class HostapdMgr : public NetMsg SubscriberStateTable m_confHostapdGlobalTbl; SubscriberStateTable m_confRadiusServerTable; SubscriberStateTable m_confRadiusGlobalTable; - SubscriberStateTable m_mgmtIntfTbl; - SubscriberStateTable m_IntfTbl; - SubscriberStateTable m_VlanIntfTbl; - SubscriberStateTable m_LoIntfTbl; - SubscriberStateTable m_PoIntfTbl; hostapd_glbl_info_t m_glbl_info; hostapd_intf_info_map_t m_intf_info; @@ -122,8 +103,6 @@ class HostapdMgr : public NetMsg bool processHostapdConfigGlobalTblEvent(Selectable *tbl); bool processRadiusServerTblEvent(Selectable *tbl); bool processRadiusGlobalTblEvent(Selectable *tbl); - bool processMgmtIntfTblEvent(Selectable *tbl); - bool processIntfTblEvent(Selectable *tbl); void writeToFile(const string& filename, const string& value); void informHostapd(const string& type, const vector & interfaces); @@ -133,10 +112,6 @@ class HostapdMgr : public NetMsg int waitForHostapdInit(pid_t hostapd_pid); void sendSignal(void); void updateRadiusServer(); - void hostapdDot1xWpaEventSend(const string& interface, const string& event, string& val); - int hostapdWpaSyncSend(const char *ctrl_ifname, const char * cmd, char *buf, size_t *len); - void setPortDot1xTimeoutParams(); - bool IsSourceIntf(const string interface); }; #endif // _HOSTAPDMGR_H_ diff --git a/hostapdmgr/hostapdmgr_main.cpp b/hostapdmgr/hostapdmgr_main.cpp index d570c11..9e97a94 100644 --- a/hostapdmgr/hostapdmgr_main.cpp +++ b/hostapdmgr/hostapdmgr_main.cpp @@ -21,7 +21,6 @@ #include #include "hostapdmgr.h" #include -#include "ebpf/libebpf.h" int main(int argc, char *argv[]) { @@ -31,8 +30,6 @@ int main(int argc, char *argv[]) swss::DBConnector log_db(LOGLEVEL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); HostapdMgr hostapd(&configDb, &appDb); - DebugShCmdHandler dbg_hdlr(&log_db, "HOSTAPDMGRD"); - try { SWSS_LOG_NOTICE("-----Starting HostapdMgr-----"); @@ -40,15 +37,11 @@ int main(int argc, char *argv[]) //register for the table events swss::Select s; s.addSelectables(hostapd.getSelectables()); - s.addSelectables(dbg_hdlr.getSelectables()); //register for the table events NetLink netlink; netlink.registerGroup(RTNLGRP_LINK); netlink.dumpRequest(RTM_GETLINK); - netlink.setDumpIntrErrorCallback(hostapdHandleDumpError, &netlink); - attach_ebpf_filter(netlink.getFd(), "/lib/ebpf/pac_filter.bpf"); - SWSS_LOG_DEBUG("Attaching pac ebpf filter"); // kill any stale hostapd hostapd.killHostapd(); @@ -107,11 +100,7 @@ int main(int argc, char *argv[]) ret = s.select(&sel); - if (dbg_hdlr.isDebugSelectable(sel)) - { - dbg_hdlr.process(sel); - } - else if (sel != &netlink) + if (sel != &netlink) { //Pass on the processing to the Hostapd Manager hostapd.processDbEvent(sel); @@ -126,10 +115,3 @@ int main(int argc, char *argv[]) return -1; } -void hostapdHandleDumpError(void *cbData) -{ - SWSS_LOG_ENTER(); - NetLink *netlink = (NetLink *)cbData; - SWSS_LOG_NOTICE("Netlink dump failed with NLE_DUMP_INTR, resending dump request"); - netlink->dumpRequest(RTM_GETLINK); -} diff --git a/mabmgr/mabmgr.cpp b/mabmgr/mabmgr.cpp index 866e8be..3507280 100644 --- a/mabmgr/mabmgr.cpp +++ b/mabmgr/mabmgr.cpp @@ -33,59 +33,17 @@ MabMgr *mab; const string INTFS_PREFIX = "E"; -DEBUGSH_CLI(MabMgrRadiusStats, - "show system internal mabmgr radius-stats", - SHOW_COMMAND, - SYSTEM_DEBUG_COMMAND, - INTERNAL_COMMAND, - "MabMgr related commands", - "Radius stats") -{ - mab->showDebugInfo(this); -} - - -mabGlobalConfigCacheParams_t MabMgr::mabGlobalConfigTable = { MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF, - MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF, - MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF }; - MabMgr::MabMgr(DBConnector *configDb, DBConnector *stateDb, DBConnector *appDb) : m_confMabPortTbl(configDb, "MAB_PORT_CONFIG_TABLE"), - m_confMabGlobalTbl(configDb, "MAB_GLOBAL_CONFIG_TABLE"), m_confRadiusServerTable(configDb, "RADIUS_SERVER"), - m_confRadiusGlobalTable(configDb, "RADIUS"), - m_mgmtIntfTbl(appDb, "MGMT_INTF_TABLE"), - m_IntfTbl(configDb, CFG_INTF_TABLE_NAME), - m_VlanIntfTbl(configDb, CFG_VLAN_INTF_TABLE_NAME), - m_LoIntfTbl(configDb, CFG_LOOPBACK_INTERFACE_TABLE_NAME), - m_PoIntfTbl(configDb, CFG_LAG_INTF_TABLE_NAME) { + m_confRadiusGlobalTable(configDb, "RADIUS") { Logger::linkToDbNative("mabmgr"); - SWSS_LOG_DEBUG("Installing MabMgr commands"); mab = this; - DebugShCmd::install(new MabMgrRadiusStats()); - -} - -void MabMgr::showDebugInfo(DebugShCmd *cmd) -{ - char buffer[MABD_CMD_BUFFSZ]; - - memset(buffer, 0, sizeof(buffer)); - - if (L7_SUCCESS == mabRadiusClientGetStats(buffer, sizeof(buffer))) - { - DEBUGSH_OUT(cmd, "Dumping MabMgr radius stats\n\n"); - DEBUGSH_OUT(cmd, "==============================================\n"); - - DEBUGSH_OUT(cmd, "%s", buffer); - DEBUGSH_OUT(cmd, "\n==============================================\n\n"); - } } std::vector MabMgr::getSelectables() { - vector selectables{ &m_confMabPortTbl, &m_confMabGlobalTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable, - &m_mgmtIntfTbl, &m_IntfTbl, &m_VlanIntfTbl, &m_PoIntfTbl, &m_LoIntfTbl }; + vector selectables{ &m_confMabPortTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable }; return selectables; } @@ -100,10 +58,6 @@ bool MabMgr::processDbEvent(Selectable *tbl) { return processMabConfigPortTblEvent(tbl); } - if (tbl == ((Selectable *) & m_confMabGlobalTbl)) { - return processMabConfigGlobalTblEvent(tbl); - } - if (tbl == ((Selectable *) & m_confRadiusServerTable)) { return processRadiusServerTblEvent(tbl); } @@ -112,17 +66,6 @@ bool MabMgr::processDbEvent(Selectable *tbl) { return processRadiusGlobalTblEvent(tbl); } - if (tbl == ((Selectable *) & m_mgmtIntfTbl)) { - return processMgmtIntfTblEvent(tbl); - } - - if ((tbl == ((Selectable *) & m_IntfTbl)) || - (tbl == ((Selectable *) & m_VlanIntfTbl)) || - (tbl == ((Selectable *) & m_LoIntfTbl)) || - (tbl == ((Selectable *) & m_PoIntfTbl))) { - return processIntfTblEvent(tbl); - } - SWSS_LOG_DEBUG("Received event UNKNOWN to MAB, ignoring "); return false; } @@ -151,7 +94,7 @@ bool MabMgr::processMabConfigPortTblEvent(Selectable *tbl) std::string key = kfvKey(entry); std::string op = kfvOp(entry); bool task_result = false; - L7_uint32 intIfNum; + uint32 intIfNum; SWSS_LOG_DEBUG("Received %s as key and %s as OP", key.c_str(), op.c_str()); @@ -161,7 +104,7 @@ bool MabMgr::processMabConfigPortTblEvent(Selectable *tbl) continue; } - if(fpGetIntIfNumFromHostIfName(key.c_str(), &intIfNum) != L7_SUCCESS) + if(fpGetIntIfNumFromHostIfName(key.c_str(), &intIfNum) != SUCCESS) { SWSS_LOG_NOTICE("Unable to get the internal interface number for %s.", key.c_str()); continue; @@ -181,7 +124,7 @@ bool MabMgr::processMabConfigPortTblEvent(Selectable *tbl) return true; } -bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum) +bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, uint32 & intIfNum) { SWSS_LOG_ENTER(); const std::string & key = kfvKey(t); @@ -190,7 +133,6 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & mabPortConfigCacheParams_t mabPortConfigCache; mabPortConfigCache.mab_enable = MABMGR_MAB_PORT_ENABLE_DEF; mabPortConfigCache.mab_auth_type = MABMGR_MAB_PORT_AUTH_TYPE_DEF; - mabPortConfigCache.mab_server_timeout = MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF; for (auto item = kfvFieldsValues(t).begin(); item != kfvFieldsValues(t).end(); item++) { @@ -200,9 +142,9 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & if (field == "mab_enable") { if (value == "true") - mabPortConfigCache.mab_enable = L7_ENABLE; + mabPortConfigCache.mab_enable = ENABLE; else if (value == "false") - mabPortConfigCache.mab_enable = L7_DISABLE; + mabPortConfigCache.mab_enable = DISABLE; else { SWSS_LOG_WARN("Invalid configuration option received for mab enable: %s", value.c_str()); continue; @@ -211,20 +153,16 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & if (field == "mab_auth_type") { if (value == "pap") - mabPortConfigCache.mab_auth_type= L7_AUTHMGR_PORT_MAB_AUTH_TYPE_PAP; + mabPortConfigCache.mab_auth_type= AUTHMGR_PORT_MAB_AUTH_TYPE_PAP; else if (value == "chap") - mabPortConfigCache.mab_auth_type = L7_AUTHMGR_PORT_MAB_AUTH_TYPE_CHAP; + mabPortConfigCache.mab_auth_type = AUTHMGR_PORT_MAB_AUTH_TYPE_CHAP; else if (value == "eap-md5") - mabPortConfigCache.mab_auth_type = L7_AUTHMGR_PORT_MAB_AUTH_TYPE_EAP_MD5; + mabPortConfigCache.mab_auth_type = AUTHMGR_PORT_MAB_AUTH_TYPE_EAP_MD5; else { SWSS_LOG_WARN("Invalid configuration option received for mab auth type: %s", value.c_str()); continue; } } - if (field == "server_timeout") - { - mabPortConfigCache.mab_server_timeout = (unsigned int)stoi(value); - } } mabPortConfigTableMap::iterator iter = m_mabPortConfigMap.find(key); @@ -235,7 +173,7 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & if(mabPortConfigCache.mab_enable != MABMGR_MAB_PORT_ENABLE_DEF) { - if (L7_SUCCESS != mabPortMABEnableSet(intIfNum, mabPortConfigCache.mab_enable)) + if ( SUCCESS != mabPortMABEnableSet(intIfNum, mabPortConfigCache.mab_enable)) { iter->second.mab_enable = MABMGR_MAB_PORT_ENABLE_DEF; SWSS_LOG_ERROR("Unable to enable MAB operationally."); @@ -243,20 +181,12 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & } if(mabPortConfigCache.mab_auth_type != MABMGR_MAB_PORT_AUTH_TYPE_DEF) { - if (L7_SUCCESS != mabPortMABAuthTypeSet(intIfNum, mabPortConfigCache.mab_auth_type)) + if ( SUCCESS != mabPortMABAuthTypeSet(intIfNum, mabPortConfigCache.mab_auth_type)) { iter->second.mab_auth_type = MABMGR_MAB_PORT_AUTH_TYPE_DEF; SWSS_LOG_ERROR("Unable to set MAB authentication type operationally."); } } - if(MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF != mabPortConfigCache.mab_server_timeout) - { - if (L7_SUCCESS != mabPortMABServerTimeoutSet(intIfNum, mabPortConfigCache.mab_server_timeout)) - { - iter->second.mab_server_timeout = MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF; - SWSS_LOG_ERROR("Unable to set MAB port server timeout."); - } - } } else //Interface entry already exists in local cache, check for any parameter change for Add/Update/Delete { @@ -266,7 +196,7 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & ((iter->second.mab_enable != MABMGR_MAB_PORT_ENABLE_DEF) && (mabPortConfigCache.mab_enable != iter->second.mab_enable))) { - if (L7_SUCCESS == mabPortMABEnableSet(intIfNum, mabPortConfigCache.mab_enable)) + if ( SUCCESS == mabPortMABEnableSet(intIfNum, mabPortConfigCache.mab_enable)) { iter->second.mab_enable = mabPortConfigCache.mab_enable; } @@ -282,7 +212,7 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & ((iter->second.mab_auth_type != MABMGR_MAB_PORT_AUTH_TYPE_DEF) && (mabPortConfigCache.mab_auth_type != iter->second.mab_auth_type))) { - if (L7_SUCCESS == mabPortMABAuthTypeSet(intIfNum, mabPortConfigCache.mab_auth_type)) + if ( SUCCESS == mabPortMABAuthTypeSet(intIfNum, mabPortConfigCache.mab_auth_type)) { iter->second.mab_auth_type = mabPortConfigCache.mab_auth_type; } @@ -292,24 +222,11 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & return false; } } - if (iter->second.mab_server_timeout != mabPortConfigCache.mab_server_timeout) - { - if (L7_SUCCESS == - mabPortMABServerTimeoutSet(intIfNum, mabPortConfigCache.mab_server_timeout)) - { - iter->second.mab_server_timeout = mabPortConfigCache.mab_server_timeout; - } - else - { - SWSS_LOG_ERROR("Unable to set MAB port server timeout."); - return false; - } - } } return true; } -bool MabMgr::doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum) +bool MabMgr::doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, uint32 & intIfNum) { SWSS_LOG_ENTER(); const std::string & key = kfvKey(t); @@ -318,7 +235,7 @@ bool MabMgr::doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, L7_uint3 { if (iter->second.mab_enable != MABMGR_MAB_PORT_ENABLE_DEF) { - if (L7_SUCCESS == mabPortMABEnableSet(intIfNum, MABMGR_MAB_PORT_ENABLE_DEF)) + if ( SUCCESS == mabPortMABEnableSet(intIfNum, MABMGR_MAB_PORT_ENABLE_DEF)) { iter->second.mab_enable = MABMGR_MAB_PORT_ENABLE_DEF; } @@ -330,7 +247,7 @@ bool MabMgr::doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, L7_uint3 } if (iter->second.mab_auth_type != MABMGR_MAB_PORT_AUTH_TYPE_DEF) { - if (L7_SUCCESS == mabPortMABAuthTypeSet(intIfNum, MABMGR_MAB_PORT_AUTH_TYPE_DEF)) + if ( SUCCESS == mabPortMABAuthTypeSet(intIfNum, MABMGR_MAB_PORT_AUTH_TYPE_DEF)) { iter->second.mab_auth_type = MABMGR_MAB_PORT_AUTH_TYPE_DEF; } @@ -340,208 +257,6 @@ bool MabMgr::doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, L7_uint3 return false; } } - if (MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF != iter->second.mab_server_timeout) - { - if (L7_SUCCESS == - mabPortMABServerTimeoutSet(intIfNum, MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF)) - { - iter->second.mab_server_timeout = MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF; - } - else - { - SWSS_LOG_ERROR("Unable to set MAB port server timeout."); - return false; - } - } - } - return true; -} - -bool MabMgr::processMabConfigGlobalTblEvent(Selectable *tbl) -{ - SWSS_LOG_DEBUG("Received a table config event on MAB_GLOBAL_CONFIG_TABLE table"); - - std::deque entries; - m_confMabGlobalTbl.pops(entries); - - SWSS_LOG_DEBUG("Received %d entries", (int) entries.size()); - - /* Nothing popped */ - if (entries.empty()) - { - return false; - } - - // Check through all the data - for (auto entry : entries) - { - std::string key = kfvKey(entry); - std::string op = kfvOp(entry); - bool task_result = false; - - SWSS_LOG_DEBUG("Received %s as key and %s as OP", key.c_str(), op.c_str()); - - if (op == SET_COMMAND) - { - task_result = doMabGlobalTableSetTask(entry); - } - else if (op == DEL_COMMAND) - { - task_result = doMabGlobalTableDeleteTask(); - } - if (!task_result) - return false; - } - return true; -} - -bool MabMgr::doMabGlobalTableSetTask(const KeyOpFieldsValuesTuple & t) -{ - SWSS_LOG_ENTER(); - - // Update mabGlobalConfigCache with incoming table data - mabGlobalConfigCacheParams_t mabGlobalConfigCache; - mabGlobalConfigCache.group_size = MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF; - mabGlobalConfigCache.separator = MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF; - mabGlobalConfigCache.attrCase = MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF; - - for (auto item = kfvFieldsValues(t).begin(); item != kfvFieldsValues(t).end(); item++) - { - const std::string & field = fvField(*item); - const std::string & value = fvValue(*item); - - if (field == "group_size") - { - if(value == "1") - mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_1; - else if(value == "2") - mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_2; - else if(value == "4") - mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_4; - else if(value == "12") - mabGlobalConfigCache.group_size = L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_12; - else { - SWSS_LOG_WARN("Invalid option recieved for groupsize MAB request format attribute1: %s", value.c_str()); - continue; - } - } - if (field == "separator") - { - if(value == "-") - mabGlobalConfigCache.separator = L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_IETF; - else if(value == ":") - mabGlobalConfigCache.separator = L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_LEGACY; - else if(value == ".") - mabGlobalConfigCache.separator = L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_DOT; - else { - SWSS_LOG_WARN("Invalid option recieved for separator MAB request format attribute1: %s", value.c_str()); - continue; - } - } - if (field == "case") - { - if(value == "lowercase") - mabGlobalConfigCache.attrCase = L7_MAB_REQUEST_ATTRIBUTE1_CASE_LOWER; - else if(value == "uppercase") - mabGlobalConfigCache.attrCase = L7_MAB_REQUEST_ATTRIBUTE1_CASE_UPPER; - else { - SWSS_LOG_WARN("Invalid option recieved for case MAB request format attribute1: %s", value.c_str()); - continue; - } - } - } - - // Update MAB global config placeholder with table updates - // group_size - if (((mabGlobalConfigTable.group_size == MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF) && - (mabGlobalConfigCache.group_size != MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF)) || - ((mabGlobalConfigTable.group_size != MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF) && - (mabGlobalConfigCache.group_size != mabGlobalConfigTable.group_size))) - { - if (L7_SUCCESS == mabRequestFormatAttribut1GroupSizeSet(mabGlobalConfigCache.group_size)) - { - mabGlobalConfigTable.group_size = mabGlobalConfigCache.group_size; - } - else - { - SWSS_LOG_ERROR("Unable to set the groupsize for formatting the MAB attribute1."); - return false; - } - } - // separator - if (((mabGlobalConfigTable.separator == MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF) && - (mabGlobalConfigCache.separator != MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF)) || - ((mabGlobalConfigTable.separator != MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF) && - (mabGlobalConfigCache.separator != mabGlobalConfigTable.separator))) - { - if (L7_SUCCESS == mabRequestFormatAttribute1SeparatorSet(mabGlobalConfigCache.separator)) - { - mabGlobalConfigTable.separator = mabGlobalConfigCache.separator; - } - else - { - SWSS_LOG_ERROR("Unable to set the separator for formatting the MAB attribute1."); - return false; - } - } - // case - if (((mabGlobalConfigTable.attrCase == MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF) && - (mabGlobalConfigCache.attrCase != MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF)) || - ((mabGlobalConfigTable.attrCase != MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF) && - (mabGlobalConfigCache.attrCase != mabGlobalConfigTable.attrCase))) - { - if (L7_SUCCESS == mabRequestFormatAttribute1CaseSet(mabGlobalConfigCache.attrCase)) - { - mabGlobalConfigTable.attrCase = mabGlobalConfigCache.attrCase; - } - else - { - SWSS_LOG_ERROR("Unable to set the case for formatting the MAB attribute1."); - return false; - } - } - return true; -} - -bool MabMgr::doMabGlobalTableDeleteTask() -{ - SWSS_LOG_ENTER(); - - if (mabGlobalConfigTable.group_size != MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF) - { - if (L7_SUCCESS == mabRequestFormatAttribut1GroupSizeSet(MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF)) - { - mabGlobalConfigTable.group_size = MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF; - } - else - { - SWSS_LOG_ERROR("Unable to set groupsize with default for formatting the MAB attribute1."); - return false; - } - } - if (mabGlobalConfigTable.separator != MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF) - { - if (L7_SUCCESS == mabRequestFormatAttribute1SeparatorSet(MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF)) - { - mabGlobalConfigTable.separator = MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF; - } - else - { - SWSS_LOG_ERROR("Unable to set separator with default for formatting the MAB attribute1."); - return false; - } - } - if (mabGlobalConfigTable.attrCase != MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF) - { - if (L7_SUCCESS == mabRequestFormatAttribute1CaseSet(MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF)) - { - mabGlobalConfigTable.attrCase = MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF; - } - else - { - SWSS_LOG_ERROR("Unable to set case for formatting the MAB attribute1."); - return false; - } } return true; } @@ -573,7 +288,7 @@ void MabMgr::updateRadiusServerGlobalKey(string newKey, string oldKey) { SWSS_LOG_ENTER(); bool update = false; - L7_RC_t rc = L7_FAILURE; + RC_t rc = FAILURE; if (0 == newKey.compare(oldKey)) { @@ -600,10 +315,8 @@ void MabMgr::updateRadiusServerGlobalKey(string newKey, string oldKey) { item.second.server_ip.c_str(), item.second.server_priority.c_str(), oldKey.c_str(), - item.second.server_port.c_str(), - item.second.server_vrf.c_str(), - item.second.server_source_intf.c_str()); - if (L7_SUCCESS != rc) + item.second.server_port.c_str()); + if ( SUCCESS != rc) { SWSS_LOG_ERROR("Unable to update radius server details for MAB ip = %s, port = %s, priority = %s", item.second.server_ip.c_str(), @@ -623,7 +336,7 @@ void MabMgr::updateRadiusServerGlobalKey(string newKey, string oldKey) { void MabMgr::updateRadiusServer() { SWSS_LOG_ENTER(); - L7_RC_t rc = L7_FAILURE; + RC_t rc = FAILURE; struct addrinfo* result; char ip[INET6_ADDRSTRLEN+1]; void * src = NULL; @@ -673,10 +386,8 @@ void MabMgr::updateRadiusServer() { rc = mabRadiusServerUpdate(RADIUS_MAB_SERVER_ADD, "auth", item.second.server_ip.c_str(), item.second.server_priority.c_str(), newKey.c_str(), - item.second.server_port.c_str(), - item.second.server_vrf.c_str(), - item.second.server_source_intf.c_str()); - if (L7_SUCCESS != rc) + item.second.server_port.c_str()); + if ( SUCCESS != rc) { SWSS_LOG_ERROR("Radius server update - Unable to update radius server details for MAB."); return; @@ -691,43 +402,10 @@ void MabMgr::updateRadiusServer() { return; } -void MabMgr::updateRadiusGlobalInfo() { - L7_RC_t rc = L7_FAILURE; - string nas_ip(""); - string nas_id(""); - - if (m_radius_info.nas_ip.size()) - { - nas_ip = m_radius_info.nas_ip; - nas_id = m_radius_info.nas_ip; - } - else if (m_radius_info.mgmt_ip.size()) - { - nas_ip = m_radius_info.mgmt_ip; - nas_id = m_radius_info.mgmt_ip; - } - else if (m_radius_info.mgmt_ipv6.size()) - { - nas_ip = m_radius_info.mgmt_ipv6; - nas_id = m_radius_info.mgmt_ipv6; - } - - if (nas_ip.size() && nas_id.size()) - { - rc = mabRadiusGlobalCfgUpdate(nas_ip.c_str(), nas_id.c_str()); - if (L7_SUCCESS != rc) - { - SWSS_LOG_ERROR("Unable to update radius global configuration nas ip = %s, nas_id = %s", - nas_ip.c_str(), nas_id.c_str()); - } - } - return; -} - void MabMgr::reloadRadiusServers() { SWSS_LOG_ENTER(); - L7_RC_t rc = L7_FAILURE; + RC_t rc = FAILURE; bool server_update = false; SWSS_LOG_NOTICE("Reloading RADIUS Servers for MAB"); @@ -749,9 +427,9 @@ void MabMgr::reloadRadiusServers() } rc = mabRadiusServerUpdate(RADIUS_MAB_SERVERS_RELOAD, "auth", - NULL, NULL, NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL); - if (L7_SUCCESS != rc) + if ( SUCCESS != rc) { SWSS_LOG_ERROR("RADIUS Servers reload - Unable to reload."); } @@ -791,8 +469,6 @@ bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) m_radius_info.radius_auth_server_list[key].server_port = ""; m_radius_info.radius_auth_server_list[key].server_key = ""; m_radius_info.radius_auth_server_list[key].server_priority = ""; - m_radius_info.radius_auth_server_list[key].server_vrf = ""; - m_radius_info.radius_auth_server_list[key].server_source_intf = ""; m_radius_info.radius_auth_server_list[key].server_update = true; m_radius_info.radius_auth_server_list[key].dns_ok = true; @@ -824,20 +500,12 @@ bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) { m_radius_info.radius_auth_server_list[key].server_priority = b; } - else if (a == "vrf") - { - m_radius_info.radius_auth_server_list[key].server_vrf = b; - } - else if (a == "src_intf") - { - m_radius_info.radius_auth_server_list[key].server_source_intf = b; - } } updateRadiusServer(); } else if (val == DEL_COMMAND) { - L7_RC_t rc = L7_FAILURE; + RC_t rc = FAILURE; SWSS_LOG_INFO("Delete Radius server for MAB %s ", m_radius_info.radius_auth_server_list[key].server_ip.c_str()); // server deleted @@ -845,10 +513,8 @@ bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) m_radius_info.radius_auth_server_list[key].server_ip.c_str(), m_radius_info.radius_auth_server_list[key].server_priority.c_str(), m_radius_info.radius_auth_server_list[key].server_key.c_str(), - m_radius_info.radius_auth_server_list[key].server_port.c_str(), - m_radius_info.radius_auth_server_list[key].server_vrf.c_str(), - m_radius_info.radius_auth_server_list[key].server_source_intf.c_str()); - if (rc != L7_SUCCESS) + m_radius_info.radius_auth_server_list[key].server_port.c_str()); + if (rc != SUCCESS) { SWSS_LOG_ERROR("Radius server delete - Unable to delete radius server details for MAB."); } @@ -864,7 +530,6 @@ bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("Received a RADIUS event"); string tmp_radiusGlobalKey(m_radius_info.m_radiusGlobalKey); - string tmp_nas_ip(m_radius_info.nas_ip); deque entries; m_confRadiusGlobalTable.pops(entries); @@ -886,10 +551,6 @@ bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) SWSS_LOG_NOTICE("Received %s as key and %s as OP", key.c_str(), val.c_str()); - // Removal of radius key and nas_ip as these are also sent as a SET - m_radius_info.m_radiusGlobalKey = ""; - m_radius_info.nas_ip = ""; - if (val == SET_COMMAND) { SWSS_LOG_NOTICE("SET operation on RADIUS table"); @@ -897,7 +558,6 @@ bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) // Look at the data that is sent for this key for (auto i : kfvFieldsValues(entry)) { - string a = fvField(i); string b = fvValue(i); @@ -914,138 +574,15 @@ bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) } m_radius_info.m_radiusGlobalKey = ret._2; } - else if (a == "nas_ip") - { - m_radius_info.nas_ip = b; - } } } else if (val == DEL_COMMAND) { m_radius_info.m_radiusGlobalKey = ""; - m_radius_info.nas_ip = ""; } } updateRadiusServerGlobalKey(m_radius_info.m_radiusGlobalKey, tmp_radiusGlobalKey); - if (m_radius_info.nas_ip != tmp_nas_ip) - { - updateRadiusGlobalInfo(); - } - return true; } - -bool MabMgr::processMgmtIntfTblEvent(Selectable *tbl) -{ - std::deque entries; - m_mgmtIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on MGMT_INTERFACE Table", (int) entries.size()); - - // Removal of MGMT IP also is sent as a SET - m_radius_info.mgmt_ip = ""; - m_radius_info.mgmt_ipv6 = ""; - - for (auto entry : entries) - { - std::string key = kfvKey(entry); - SWSS_LOG_NOTICE("key %s", key.c_str()); - - auto tokens = tokenize(key, ':'); - SWSS_LOG_NOTICE("size %d", tokens.size()); - - // pick only IPv4 address of the management interface - if (2 == tokens.size()) - { - // eth0:a.b.c.d/mask - auto tokens1 = tokenize(tokens[1], '/'); - SWSS_LOG_NOTICE("Management IPv4 %s", tokens1[0].c_str()); - m_radius_info.mgmt_ip = tokens1[0]; - } - else if (tokens.size() > 2) - { - // eth0:2001::64/mask. Remove "eth0:" - string ipv6Str = key.substr(5); - - auto tokens1 = tokenize(ipv6Str, '/'); - SWSS_LOG_NOTICE("Management IPv6 %s", tokens1[0].c_str()); - m_radius_info.mgmt_ipv6 = tokens1[0]; - } - } - - string mgmt_intf("eth0"); - - if (0 == m_radius_info.nas_ip.size()) - { - SWSS_LOG_NOTICE("Interface %s address update for nas ip.", mgmt_intf.c_str()); - updateRadiusGlobalInfo(); - } - - reloadRadiusServers(); - - return true; -} - -bool MabMgr::IsSourceIntf(const string interface) -{ - for (auto& item: m_radius_info.radius_auth_server_list) - { - if (item.second.server_source_intf == interface) - { - return true; - } - } - return false; -} - -bool MabMgr::processIntfTblEvent(Selectable *tbl) -{ - std::deque entries; - - if (tbl == ((Selectable *) & m_IntfTbl)) - { - m_IntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on INTERFACE Table", (int) entries.size()); - } - else if (tbl == ((Selectable *) & m_VlanIntfTbl)) - { - m_VlanIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on VLAN_INTERFACE Table", (int) entries.size()); - } - else if (tbl == ((Selectable *) & m_LoIntfTbl)) - { - m_LoIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on LOOPBACK_INTERFACE Table", (int) entries.size()); - } - else if (tbl == ((Selectable *) & m_PoIntfTbl)) - { - m_PoIntfTbl.pops(entries); - SWSS_LOG_NOTICE("Received %d entries from config event on PORTCHANNEL_INTERFACE Table", (int) entries.size()); - } - - for (auto entry : entries) - { - std::string key = kfvKey(entry); - SWSS_LOG_NOTICE("key %s", key.c_str()); - - auto key_tokens = tokenize(key, '|'); - SWSS_LOG_NOTICE("size %d", key_tokens.size()); - - if (2 == key_tokens.size()) - { - // Ethernet0|IPAddress - if (IsSourceIntf(key_tokens[0])) - { - auto ip_tokens = tokenize(key_tokens[1], '/'); - SWSS_LOG_NOTICE("Interface %s used as Source Interface. Address %s/%s", - key_tokens[0].c_str(), ip_tokens[0].c_str(), ip_tokens[1].c_str()); - reloadRadiusServers(); - break; - } - } - } - - return true; -} - diff --git a/mabmgr/mabmgr.h b/mabmgr/mabmgr.h index 34288b6..674a4db 100644 --- a/mabmgr/mabmgr.h +++ b/mabmgr/mabmgr.h @@ -38,8 +38,6 @@ typedef struct radius_server_info_s { std::string server_key; std::string server_ip; std::string server_priority; - std::string server_vrf; - std::string server_source_intf; bool server_update; bool dns_ok; }radius_server_info_t; @@ -48,32 +46,16 @@ typedef std::map radius_server_info_map_t; typedef struct radius_info_s { string m_radiusGlobalKey; - std::string nas_ip; - std::string mgmt_ip; - std::string mgmt_ipv6; radius_server_info_map_t radius_auth_server_list; - radius_server_info_map_t radius_acct_server_list; }radius_info_t; -#define MABMGR_REQUEST_ATTRIBUTE1_GROUP_SIZE_DEF L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_2 -#define MABMGR_REQUEST_ATTRIBUTE1_SEPARATOR_DEF L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_LEGACY -#define MABMGR_REQUEST_ATTRIBUTE1_CASE_DEF L7_MAB_REQUEST_ATTRIBUTE1_CASE_UPPER -#define MABMGR_MAB_PORT_ENABLE_DEF L7_DISABLE -#define MABMGR_MAB_PORT_AUTH_TYPE_DEF L7_AUTHMGR_PORT_MAB_AUTH_TYPE_EAP_MD5 -#define MABMGR_MAB_PORT_SERVER_TIMEOUT_DEF FD_MAB_PORT_SERVER_TIMEOUT - -/* MAB GLOBAL config table param cache Info */ -typedef struct { - L7_MAB_REQUEST_ATTRIBUTE1_GROUP_SIZE_t group_size; - L7_MAB_REQUEST_ATTRIBUTE1_SEPARATOR_t separator; - L7_MAB_REQUEST_ATTRIBUTE1_CASE_t attrCase; -} mabGlobalConfigCacheParams_t; +#define MABMGR_MAB_PORT_ENABLE_DEF DISABLE +#define MABMGR_MAB_PORT_AUTH_TYPE_DEF AUTHMGR_PORT_MAB_AUTH_TYPE_EAP_MD5 /* MAB port config table param cache Info */ typedef struct mabPortConfigCacheParams_t { bool mab_enable; - L7_AUTHMGR_PORT_MAB_AUTH_TYPE_t mab_auth_type; - L7_uint32 mab_server_timeout; + AUTHMGR_PORT_MAB_AUTH_TYPE_t mab_auth_type; } mabPortConfigCacheParams_t; /* MAP to store MAB port config table params, @@ -92,43 +74,24 @@ class MabMgr std::vector getSelectables(); bool processDbEvent(Selectable *source); - /* Placeholder for MAB Global table config params */ - static mabGlobalConfigCacheParams_t mabGlobalConfigTable; - - /* Debug routine. */ - void showDebugInfo(DebugShCmd *cmd); - private: //tables this component listens to SubscriberStateTable m_confMabPortTbl; - SubscriberStateTable m_confMabGlobalTbl; SubscriberStateTable m_confRadiusServerTable; SubscriberStateTable m_confRadiusGlobalTable; - SubscriberStateTable m_mgmtIntfTbl; - SubscriberStateTable m_IntfTbl; - SubscriberStateTable m_VlanIntfTbl; - SubscriberStateTable m_LoIntfTbl; - SubscriberStateTable m_PoIntfTbl; radius_info_t m_radius_info; mabPortConfigTableMap m_mabPortConfigMap; // DB Event handler functions bool processMabConfigPortTblEvent(Selectable *tbl); - bool processMabConfigGlobalTblEvent(Selectable *tbl); bool processRadiusServerTblEvent(Selectable *tbl); bool processRadiusGlobalTblEvent(Selectable *tbl); - bool processMgmtIntfTblEvent(Selectable *tbl); - bool processIntfTblEvent(Selectable *tbl); - bool doMabGlobalTableSetTask(const KeyOpFieldsValuesTuple & t); - bool doMabGlobalTableDeleteTask(); - bool doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum); - bool doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, L7_uint32 & intIfNum); + bool doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, uint32 & intIfNum); + bool doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, uint32 & intIfNum); void updateRadiusServer(); void updateRadiusServerGlobalKey(string newKey, string oldKey); - void updateRadiusGlobalInfo(); - bool IsSourceIntf(const string interface); void reloadRadiusServers() ; }; diff --git a/mabmgr/mabmgr_main.cpp b/mabmgr/mabmgr_main.cpp index 7bb5ea1..f9ac451 100644 --- a/mabmgr/mabmgr_main.cpp +++ b/mabmgr/mabmgr_main.cpp @@ -28,13 +28,13 @@ int main(int argc, char *argv[]) cout<<"Invoking fpinfraInit" << endl; fpinfraInit(); - if (mabInit () != L7_SUCCESS) + if (mabInit () != SUCCESS) cout<<"Fail" << endl; else cout<<"Success linked" << endl; - if (osapiWaitForTaskInit (L7_MAB_DB_TASK_SYNC, L7_WAIT_FOREVER) != - L7_SUCCESS) + if (osapiWaitForTaskInit ( MAB_DB_TASK_SYNC, WAIT_FOREVER) != + SUCCESS) { return -1; } @@ -54,10 +54,8 @@ int main(int argc, char *argv[]) swss::DBConnector stateDb("STATE_DB", 0); swss::DBConnector configDb("CONFIG_DB", 0); swss::DBConnector appDb("APPL_DB", 0); - swss::DBConnector log_db(LOGLEVEL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); MabMgr mab(&configDb, &stateDb, &appDb); - DebugShCmdHandler dbg_hdlr(&log_db, "MABMGRD"); // App Marking closest UP status Table feat_tbl(&stateDb, STATE_FEATURE_TABLE_NAME); @@ -80,7 +78,6 @@ int main(int argc, char *argv[]) //register for the table events swss::Select s; s.addSelectables(mab.getSelectables()); - s.addSelectables(dbg_hdlr.getSelectables()); //wait for the events and process them while (true) @@ -90,15 +87,8 @@ int main(int argc, char *argv[]) swss::Selectable *sel = NULL; s.select(&sel); - if (dbg_hdlr.isDebugSelectable(sel)) - { - dbg_hdlr.process(sel); - } - else - { - //Pass on the processing to the Mab Manager - mab.processDbEvent(sel); - } + //Pass on the processing to the Mab Manager + mab.processDbEvent(sel); } }