diff --git a/hostapdmgr/hostapdmgr.cpp b/hostapdmgr/hostapdmgr.cpp index eb6d618..ba46b5c 100644 --- a/hostapdmgr/hostapdmgr.cpp +++ b/hostapdmgr/hostapdmgr.cpp @@ -44,7 +44,8 @@ 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_confRadiusGlobalTable(configDb, "RADIUS"), + m_confHostapdUserCfgTbl(configDb, "HOSTAPD_USER_CONFIG") /*CG_PAC*/ { Logger::linkToDbNative("hostapdmgr"); @@ -68,7 +69,7 @@ string HostapdMgr::getStdIfFormat(string key) } vector HostapdMgr::getSelectables() { - vector selectables{ &m_confHostapdPortTbl, &m_confHostapdGlobalTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable}; + vector selectables{ &m_confHostapdPortTbl, &m_confHostapdGlobalTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable, &m_confHostapdUserCfgTbl /*CG_PAC*/}; return selectables; } @@ -95,11 +96,280 @@ bool HostapdMgr::processDbEvent(Selectable *tbl) { return processRadiusGlobalTblEvent(tbl); } + if (tbl == ((Selectable *) & m_confHostapdUserCfgTbl)) { /*CG_PAC*/ + return processHostapdUserCfgTblEvent(tbl); + } + SWSS_LOG_DEBUG("Received event UNKNOWN to HOSTAPD, ignoring "); return false; } //Process the config db table events +bool HostapdMgr::processHostapdUserCfgTblEvent(Selectable *tbl) +{ /*CG_PAC*/ + bool ret_flag = false; + deque db_entries; + + SWSS_LOG_ENTER(); + m_confHostapdPortTbl.pops(db_entries); + SWSS_LOG_DEBUG("Received HOSTAPD_USER_CONFIG DB table event with %d entries", (int) db_entries.size()); + + if (db_entries.empty()) + { + SWSS_LOG_NOTICE("No entries in HOSTAPD_USER_CONFIG DB Table, Skip further processing", (int) db_entries.size()); + return ret_flag; + } + + for (auto db_entry : db_entries) + { + string key = kfvKey(db_entry); + string val = kfvOp(db_entry); + + SWSS_LOG_DEBUG("Received %s as key and %s as OP", key.c_str(), val.c_str()); + + if (op == SET_COMMAND) + { + ret_flag = doHostapdUserCfgTableSetTask(db_entry) + } + else if (op == DEL_COMMAND) + { + ret_flag = doHostapdUserCfgTableDeleteTask(db_entry) + } + if (false == ret_flag) + { + SWSS_LOG_ERROR("Failed at %s HostapdUserConfig key handling", key.c_str()); + return ret_flag; + } + } + return true; +} + +void HostapdMgr::updateUserConfigFile(const string& username_key) +{/*CG_PAC*/ + SWSS_LOG_ENTER(); + struct stat buffer; + + // Check if the file exists + if (stat(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH, &buffer) != 0) + { + SWSS_LOG_ERROR("Hostapd User Config file does not exist."); + return; + } + + hostapdUserConfigTableMap::iterator iter = m_hostapdUserConfigMap.find(username_key); + if (iter != m_hostapdUserConfigMap.end()) + { + string username_key = iter->first; + string auth_type = iter->second.auth_type; + string password = iter->second.password; + + ifstream infile(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH); + string line; + string updatedContent; + bool found = false; + + // Read the existing content and update the user's information + while (getline(infile, line)) + { + size_t posUsername = line.find(username_key); + size_t posAuthType = line.find(auth_type); + + if (posUsername != string::npos && posAuthType != string::npos) + { + // Both username_key and auth_type match, so update the password + updatedContent += username_key + " " + auth_type + " " + password + "\n"; + found = true; + } + else + { + // Keep the line as is if there's no match + updatedContent += line + "\n"; + } + } + + infile.close(); + + if (found) + { + // Print the updated content for testing + SWSS_LOG_NOTICE("Updated Content:\n%s", updatedContent.c_str()); + + // Write to the file + writeToFile(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH, updatedContent); + } + else + { + SWSS_LOG_ERROR("Username key %s not found in Hostapad User Config.", username_key.c_str()); + string newEntry = username_key + " " + auth_type + " " + password; + updatedContent += newEntry + "\n"; + writeToFile(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH, updatedContent); + } + } + else + { + SWSS_LOG_ERROR("Username key %s not found in Hostapad User Config.", username_key.c_str()); + } +} + +void HostapdMgr::deleteUserConfigFile(const string& username_key) +{ /*CG_PAC*/ + SWSS_LOG_ENTER(); + struct stat buffer; + + // Check if the file exists + if (stat(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH, &buffer) != 0) + { + SWSS_LOG_ERROR("Hostapd User Config file does not exist."); + return; + } + + ifstream configFileIn(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH); + if (!configFileIn.is_open()) + { + SWSS_LOG_ERROR("Failed to open Hostapd User Config file for reading."); + return; + } + + string line; + string updatedContent = ""; + bool entryFound = false; + + // Read the file line by line, and skip the line with the specified username_key + while (getline(configFileIn, line)) + { + size_t pos = line.find(username_key); + if (pos == string::npos) + { + updatedContent += line + "\n"; + } + else + { + entryFound = true; + } + } + + configFileIn.close(); + + if (!entryFound) + { + SWSS_LOG_ERROR("username: %s", username_key.c_str() "not found in Hostapd User Config file. Deletion failed."); + return; + } + + // Write the updated content back to the file + writeToFile(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH, updatedContent); + + SWSS_LOG_DEBUG("Deleted Hostapd User Config entry for username: %s", username_key.c_str()); +} + +void HostapdMgr::createUserConfigFile(const string& username_key) +{/*CG_PAC*/ + SWSS_LOG_ENTER(); + string content = ""; + struct stat buffer; + + // Use the stat function to check if the file exists + if(stat(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH, &buffer) != 0) + {//File doesn't exist, create file + fstream file; + file.open(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH,ios::out); + if(!file) + { + SWSS_LOG_ERROR("Failed to create Hostapd User Config file"); + return ; + } + SWSS_LOG_ERROR("Successfully created Hostapd User Config file"); + file.close(); + } + + hostapdUserConfigTableMap ::iterator iter = m_hostapdUserConfigMap.find(username_key); + if(iter != m_hostapdUserConfigMap.end()) + { + // Create the content for the user configuration file + content = username_key + " " + iter->second.auth_type + " " + iter->second.password; + SWSS_LOG_DEBUG("Framed HostapdUserConfig Content: %s ", content.c_str()); + + // Write to the file + writeToFile(HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH, content); + } + //TODO: Inform Hostapd Service needed ? +} +/* Key is MAC Address of client + * Value is hostapdUserConfigCacheParams_t + * */ +bool HostapdMgr::doHostapdUserCfgTableSetTask(const KeyOpFieldsValuesTuple & t) +{ /*CG_PAC*/ + const std::string & key = kfvKey(t); + hostapdUserConfigCacheParams_t hostapdUserConfigCache; + + SWSS_LOG_ENTER(); + /*Initialize with default values*/ + hostapdUserConfigCache.auth_type = HOSTAPDMGR_HOSTAPD_USER_AUTH_TYPE_DEF; + hostapdUserConfigCache.password = HOSTAPDMGR_HOSTAPD_USER_PASSWORD_DEF; + hostapdUserConfigCache.vlan_id = HOSTAPDMGR_HOSTAPD_USER_VLAN_ID_DEF; + hostapdUserConfigCache.session_timeout = HOSTAPDMGR_HOSTAPD_USER_SESSION_TIMEOUT_DEF; + + for (auto item = kfvFieldsValues(t).begin(); item != kfvFieldsValues(t).end(); item++) + { + const std::string & field = fvField(*item); + std::string value = fvValue(item); + + if (field == "vlan_id") + { + hostapdUserConfigCache.vlan_id = stoi(value); + SWSS_LOG_DEBUG("MAB UserConfig Set Task: vlan_id is key and %d is vlaue", hostapdUserConfigCache.vlan_id); + } + if (field == "session_timeout") + { + hostapdUserConfigCache.session_timeout = stoi(value); + SWSS_LOG_DEBUG("MAB UserConfig Set Task: session_timeout is key and %d is vlaue", hostapdUserConfigCache.session_timeout); + } + if (field == "password") + { + hostapdUserConfigCache.password = value ; + SWSS_LOG_DEBUG("MAB UserConfig Set Task: Password is key and %s is vlaue", hostapdUserConfigCache.password.c_str()); + } + if (field == "auth_type") + { + hostapdUserConfigCache.auth_type = value ; + SWSS_LOG_DEBUG("MAB UserConfig Set Task: AuthType is key and %s is vlaue", hostapdUserConfigCache.auth_type.c_str()); + } + } + + hostapdUserConfigTableMap ::iterator iter = m_hostapdUserConfigMap.find(key); + if(iter == m_hostapdUserConfigMap.end()) + { + m_hostapdUserConfigMap.insert(pair(key, hostapdUserConfigCache)); + createUserConfigFile(key); + } + else + { + iter->second.vlan_id = hostapdUserConfigCache.vlan_id; + iter->second.session_timeout = hostapdUserConfigCache.session_timeout; + iter->second.auth_type = hostapdUserConfigCache.auth_type; + iter->second.password = hostapdUserConfigCache.password; + updateUserConfigFile(key); + } + return true; +} + +bool HostapdMgr::doHostapdUserCfgTableDeleteTask(const KeyOpFieldsValuesTuple & t) +{ /*CG_PAC*/ + SWSS_LOG_ENTER(); + const std::string & key = kfvKey(t); + hostapdUserConfigTableMap::iterator iter = m_hostapdUserConfigMap.find(key); + if(iter != m_hostapdUserConfigMap.end()) + { + SWSS_LOG_DEBUG("Deleting MAP entry for key %s in HostapdMgr", key.c_str()); + m_hostapdUserConfigMap.erase(key); + deleteUserConfigFromFile(key);//TODO + } + else + { + SWSS_LOG_DEBUG("No entry exist corresponding to key %s in HostapdMgr, ignore", key.c_str()); + } + return true; +} bool HostapdMgr::processHostapdConfigPortTblEvent(Selectable *tbl) { @@ -175,7 +445,16 @@ bool HostapdMgr::processHostapdConfigPortTblEvent(Selectable *tbl) /* update interfaces list */ new_interfaces.push_back(key); } - } + else 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_glbl_info.auth_order_list == "local")) + { //CG_PAC + /* create config file */ + createLocalConfFile(key); + + /* update interfaces list */ + new_interfaces.push_back(key); + } + } else { // pae role none @@ -205,7 +484,16 @@ bool HostapdMgr::processHostapdConfigPortTblEvent(Selectable *tbl) /* update interfaces list */ new_interfaces.push_back(key); } - } + else 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_glbl_info.auth_order_list == "local")) + { + /* create config file */ + createLocalConfFile(key); + + /* update interfaces list */ + new_interfaces.push_back(key); + } + } else { // pae role none @@ -275,6 +563,12 @@ bool HostapdMgr::processHostapdConfigGlobalTblEvent(Selectable *tbl) vector interfaces; + / *CG_PAC*/ + if (a == "auth_order_list") + { + m_glbl_info.auth_order_list = b; + } + if (a == "dot1x_system_auth_control" ) { if (b == "true") @@ -300,6 +594,15 @@ bool HostapdMgr::processHostapdConfigGlobalTblEvent(Selectable *tbl) /* update interfaces list */ interfaces.push_back(entry.first); } + else if ((entry.second.capabilities == "authenticator") && (entry.second.control_mode == "auto") && + (entry.second.link_status) && (!entry.second.config_created) && (m_glbl_info.auth_order_list == "local")) + { //CG_PAC + /* create config file */ + createLocalConfFile(entry.first); + + /* update interfaces list */ + interfaces.push_back(entry.first); + } } /* Update JSON */ @@ -473,7 +776,27 @@ void HostapdMgr::updateRadiusServer() { informHostapd("modified", interfaces); return; } + else if (m_glbl_info.enable_auth && m_glbl_info.auth_order_list == "local") + { //CG_PAC + 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 */ + createLocalConfFile(entry.first); + + /* update interfaces list */ + interfaces.push_back(entry.first); + } + } + /* update JSON file */ + informHostapd("modified", interfaces); + return; + } // Check if global auth is enabled or not else if (!m_glbl_info.enable_auth || m_radiusServerInUse == "") { @@ -782,6 +1105,18 @@ void HostapdMgr::onMsg(int nlmsg_type, struct nl_object *obj) /* update JSON file */ informHostapd("new", interfaces); } + else if ((m_intf_info[key1].link_status) && (!m_intf_info[key1].config_created) && + (m_glbl_info.auth_order_list == "local")) + { //CG_PAC + /* create config file */ + createLocalConfFile(key1); + + /* update interfaces list */ + interfaces.push_back(key1); + + /* update JSON file */ + informHostapd("new", interfaces); + } /* down't bring down hostapd interface when admin state goes down. * it will get deleted with RTM_DELLINK. */ @@ -1173,6 +1508,55 @@ void HostapdMgr::createConfFile(const string& intf) m_intf_info[intf].config_created = true; } +void HostapdMgr::createLocalConfFile(const string& intf) +{ //CG_PAC + 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=1\n"; //NOTE: Different from remote config + content += "eap_user_file=/etc/hostapd/hostapd.eap_user\n"//NOTE: Different from remote config + + 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(); diff --git a/hostapdmgr/hostapdmgr.h b/hostapdmgr/hostapdmgr.h index c0cf2bd..1a26068 100644 --- a/hostapdmgr/hostapdmgr.h +++ b/hostapdmgr/hostapdmgr.h @@ -36,10 +36,17 @@ using namespace swss; using namespace std; +#define HOSTAPDMGR_HOSTAPD_USER_CONFIG_FILE_PATH "/etc/hostapd/hostapd.eap_user" /*CG_PAC*/ +#define HOSTAPDMGR_HOSTAPD_USER_AUTH_TYPE_DEF "MD5" /*CG_PAC*/ +#define HOSTAPDMGR_HOSTAPD_USER_PASSWORD_DEF "" /*CG_PAC*/ +#define HOSTAPDMGR_HOSTAPD_USER_VLAN_ID_DEF 0 /*CG_PAC*/ +#define HOSTAPDMGR_HOSTAPD_USER_SESSION_TIMEOUT_DEF 60 /*CG_PAC*/ + void hostapdHandleDumpError(void *cbData); typedef struct hostapd_glbl_info_s { unsigned int enable_auth; + std::string auth_order_list; /*CG_PAC*/ }hostapd_glbl_info_t; typedef struct hostapd_intf_info_s { @@ -67,6 +74,21 @@ typedef struct radius_info_s { typedef std::map hostapd_intf_info_map_t; +/*CG_PAC*/ +/* Hostapd User config table param cache Info */ +typedef struct hostapdUserConfigCacheParams_t { + std::string password; /*Password of the user/supplicant*/ + std::string auth_type; /*Supported Authentication Type. Default: eap-md5*/ + int vlan_id; /*VLAN to be associated with the authorized client*/ + int session_timeout; /*Client session time*/ +} hostapdUserConfigCacheParams_t; + +/*MAP to store Hostapd user configuration table parameters + * Key: MAC Address of Supplicant + * Value: hostapdUserConfigCacheParams_t + * */ +typedef std::map hostapdUserConfigTableMap; + class HostapdMgr : public NetMsg { public: @@ -84,7 +106,9 @@ class HostapdMgr : public NetMsg SubscriberStateTable m_confHostapdGlobalTbl; SubscriberStateTable m_confRadiusServerTable; SubscriberStateTable m_confRadiusGlobalTable; + SubscriberStateTable m_confHostapdUserCfgTbl; /*CG_PAC*/ + hostapdUserConfigTableMap m_hostapdUserConfigMap; //CG_PAC hostapd_glbl_info_t m_glbl_info; hostapd_intf_info_map_t m_intf_info; radius_info_t m_radius_info; @@ -103,10 +127,12 @@ class HostapdMgr : public NetMsg bool processHostapdConfigGlobalTblEvent(Selectable *tbl); bool processRadiusServerTblEvent(Selectable *tbl); bool processRadiusGlobalTblEvent(Selectable *tbl); + bool processHostapdUserCfgTblEvent(Selectable *tbl); void writeToFile(const string& filename, const string& value); void informHostapd(const string& type, const vector & interfaces); void createConfFile(const string& intf); + void createLocalConfFile(const string& intf); //CG_PAC void deleteConfFile(const string& intf); pid_t getHostapdPid(void); int waitForHostapdInit(pid_t hostapd_pid); diff --git a/mabmgr/mabmgr.cpp b/mabmgr/mabmgr.cpp index 3507280..08f3b0a 100644 --- a/mabmgr/mabmgr.cpp +++ b/mabmgr/mabmgr.cpp @@ -36,14 +36,15 @@ const string INTFS_PREFIX = "E"; MabMgr::MabMgr(DBConnector *configDb, DBConnector *stateDb, DBConnector *appDb) : m_confMabPortTbl(configDb, "MAB_PORT_CONFIG_TABLE"), m_confRadiusServerTable(configDb, "RADIUS_SERVER"), - m_confRadiusGlobalTable(configDb, "RADIUS") { + m_confRadiusGlobalTable(configDb, "RADIUS"), + /*CG_PAC*/ m_confMabUserCfgTbl(configDb, "MAB_USER_CONFIG") { Logger::linkToDbNative("mabmgr"); mab = this; } std::vector MabMgr::getSelectables() { - vector selectables{ &m_confMabPortTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable }; + vector selectables{ &m_confMabPortTbl, &m_confRadiusServerTable, &m_confRadiusGlobalTable, &m_confMabUserCfgTbl /*CG_PAC*/}; return selectables; } @@ -65,6 +66,10 @@ bool MabMgr::processDbEvent(Selectable *tbl) { if (tbl == ((Selectable *) & m_confRadiusGlobalTable)) { return processRadiusGlobalTblEvent(tbl); } + + if (tbl == ((Selectable *) & m_confMabUserCfgTbl)) { /*CG_PAC*/ + return processMabUserCfgTblEvent(tbl); + } SWSS_LOG_DEBUG("Received event UNKNOWN to MAB, ignoring "); return false; @@ -72,6 +77,107 @@ bool MabMgr::processDbEvent(Selectable *tbl) { //Process the config db table events +bool MabMgr::processMabUserCfgTblEvent(Selectable *tbl) +{ /*CG_PAC*/ + bool ret_flag = false; + std::deque db_entries; + + SWSS_LOG_ENTER(); + m_confMabUserCfgTbl.pops(db_entries); + SWSS_LOG_DEBUG("Received MAB_USER_CONFIG DB table event with %d entries", (int) db_entries.size()); + + if (db_entries.empty()) + { + SWSS_LOG_NOTICE("No entries in MAB_USER_CONFIG DB Table, Skip further processing", (int) db_entries.size()); + return ret_flag; + } + + for (auto db_entry : db_entries) + { + std::string key = kfvKey(db_entry); + std::string op = kfvOp(db_entry); + + SWSS_LOG_DEBUG("Received %s as key and %s as OP", key.c_str(), op.c_str()); + + if (op == SET_COMMAND) + { + ret_flag = doMabUserCfgTableSetTask(db_entry) + } + else if (op == DEL_COMMAND) + { + ret_flag = doMabUserCfgTableDeleteTask(db_entry) + } + if (false == ret_flag) + { + SWSS_LOG_ERROR("Failed at %s MabUserConfig key handling", key.c_str()); + return ret_flag; + } + } + return true; +} + +/* Key is MAC Address of client + * Value is mabUserConfigCacheParams_t + * */ +bool MabMgr::doMabUserCfgTableSetTask(const KeyOpFieldsValuesTuple & t) +{/*CG_PAC*/ + const std::string & key = kfvKey(t); + mabUserConfigCacheParams_t mabUserConfigCache; + + SWSS_LOG_ENTER(); + + /*Initialize with default values*/ + mabUserConfigCache.access_type = MABMGR_MAB_USER_CFG_ACCESS_TYPE_DEF; + mabUserConfigCache.vlan_id = MABMGR_MAB_USER_VLAN_ID_DEF; + mabUserConfigCache.session_timeout = MABMGR_MAB_USER_SESSION_TIMEOUT_DEF; + + for (auto item = kfvFieldsValues(t).begin(); item != kfvFieldsValues(t).end(); item++) + { + const std::string & field = fvField(*item); + std::string value = fvValue(item); + + if (field == "vlan_id") + { + mabUserConfigCache.vlan_id = stoi(value); + SWSS_LOG_DEBUG("MAB UserConfig Set Task: vlan_id is key and %d is vlaue", mabPortConfigCache.vlan_id); + } + if (field == "session_timeout") + { + mabUserConfigCache.session_timeout = stoi(value); + SWSS_LOG_DEBUG("MAB UserConfig Set Task: session_timeout is key and %d is vlaue", mabUserConfigCache.session_timeout); + } + } + + mabUserConfigTableMap ::iterator iter = m_mabUserConfigMap.find(key); + if(iter == m_mabUserConfigMap.end()) + { + m_mabUserConfigMap.insert(pair(key, mabUserConfigCache)); + } + else + { + iter->second.vlan_id = mabUserConfigCache.vlan_id; + iter->second.session_timeout = mabUserConfigCache.session_timeout; + } + return true; +} + +bool MabMgr::doMabUserCfgTableDeleteTask(const KeyOpFieldsValuesTuple & t) +{/*CG_PATH*/ + SWSS_LOG_ENTER(); + const std::string & key = kfvKey(t); + mabUserConfigTableMap::iterator iter = m_mabUserConfigMap.find(key); + if(iter != m_mabUserConfigMap.end()) + { + SWSS_LOG_DEBUG("Deleting MAP entry for key %s", key.c_str()); + m_mabUserConfigMap.erase(key); + } + else + { + SWSS_LOG_DEBUG("No entry exist corresponding to key %s, ignore", key.c_str()); + } + return true; +} + bool MabMgr::processMabConfigPortTblEvent(Selectable *tbl) { SWSS_LOG_ENTER(); @@ -201,7 +307,7 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, uint32 & in iter->second.mab_enable = mabPortConfigCache.mab_enable; } else - { + { SWSS_LOG_ERROR("Unable to enable/disable MAB operationally."); return false; } @@ -217,7 +323,7 @@ bool MabMgr::doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, uint32 & in iter->second.mab_auth_type = mabPortConfigCache.mab_auth_type; } else - { + { SWSS_LOG_ERROR("Unable to set MAB authentication type operationally."); return false; } @@ -303,7 +409,7 @@ void MabMgr::updateRadiusServerGlobalKey(string newKey, string oldKey) { continue; } - /* Check and update Radius server if using Global key */ + /* Check and update Radius server if using Global key */ if (0 != newKey.size()) { item.second.server_update = true; @@ -348,7 +454,7 @@ void MabMgr::updateRadiusServer() { if (false == item.second.server_update) { SWSS_LOG_INFO("skipped %s as update not needed.", item.first.c_str()); - continue; + continue; } if (getaddrinfo(item.first.c_str(), NULL, NULL, &result) || result == NULL) @@ -367,14 +473,14 @@ void MabMgr::updateRadiusServer() { freeaddrinfo(result); //Check if radius server has key configured. If not, - // pick global key. If key does not exist, skip to next server. + // 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; + continue; } - string newKey = m_radius_info.m_radiusGlobalKey; + string newKey = m_radius_info.m_radiusGlobalKey; if (item.second.server_key != "") { newKey = item.second.server_key; @@ -382,7 +488,7 @@ void MabMgr::updateRadiusServer() { 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(), @@ -392,7 +498,7 @@ void MabMgr::updateRadiusServer() { 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", + 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()); @@ -402,7 +508,7 @@ void MabMgr::updateRadiusServer() { return; } -void MabMgr::reloadRadiusServers() +void MabMgr::reloadRadiusServers() { SWSS_LOG_ENTER(); RC_t rc = FAILURE; @@ -426,7 +532,7 @@ void MabMgr::reloadRadiusServers() updateRadiusServer(); } - rc = mabRadiusServerUpdate(RADIUS_MAB_SERVERS_RELOAD, "auth", + rc = mabRadiusServerUpdate(RADIUS_MAB_SERVERS_RELOAD, "auth", NULL, NULL, NULL, NULL); if ( SUCCESS != rc) @@ -437,7 +543,7 @@ void MabMgr::reloadRadiusServers() return; } -bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) +bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) { SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("Received a RADIUS_SERVER event"); @@ -494,11 +600,11 @@ bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) } else if (a == "auth_port") { - m_radius_info.radius_auth_server_list[key].server_port = b; + 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; + m_radius_info.radius_auth_server_list[key].server_priority = b; } } updateRadiusServer(); @@ -506,8 +612,8 @@ bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) else if (val == DEL_COMMAND) { 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()); + 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(), @@ -525,7 +631,7 @@ bool MabMgr::processRadiusServerTblEvent(Selectable *tbl) return true; } -bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) +bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) { SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("Received a RADIUS event"); @@ -578,7 +684,7 @@ bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) } else if (val == DEL_COMMAND) { - m_radius_info.m_radiusGlobalKey = ""; + m_radius_info.m_radiusGlobalKey = ""; } } @@ -586,3 +692,36 @@ bool MabMgr::processRadiusGlobalTblEvent(Selectable *tbl) return true; } + +/*CG_PAC*/ +int lauthClientChallengeProcess(string client_mac_key, lauth_attrInfo_t * attrInfo) +{ + int ret_auth_status = MABMGR_MAB_LAUTH_FAILED; //Authentication Failed + + SWSS_LOG_ENTER(); + SWSS_LOG_NOTICE("Received a Client challenge request from MAC %s", client_mac_key.c_str()); + if (attrInfo == NULL) + { + SWSS_LOG_ERROR("Received NULL Arguments "); + return ret_auth_status; + } + + mabUserConfigTableMap ::iterator iter = m_mabUserConfigMap.find(client_mac_key); + if(iter != m_mabUserConfigMap.end()) + { + //TODO: Memory for attrInfo : Caller will allocate memory ? + if(iter->second.access_type.c_str() == MABMGR_MAB_USER_CFG_ACCESS_TYPE_DEF) + { + attrInfo->vlanId = iter->second.vlan_id ; + attrInfo->sessionTimeout = iter->second.session_timeout ; + attrInfo->userName = client_mac_key; + attrInfo->userNameLen = strlen(client_mac_key.c_str()); + ret_auth_status = MABMGR_MAB_LAUTH_SUCCESS; + } + else + SWSS_LOG_ERROR("Incorrect Accesstype configured for MAC %s,returning auth_failure status",client_mac_key.c_str()); + } + else + SWSS_LOG_ERROR("Client MAC %s details not configured, returning auth_failure status", client_mac_key.c_str()); + return ret_auth_status ; +} diff --git a/mabmgr/mabmgr.h b/mabmgr/mabmgr.h index 674a4db..298228e 100644 --- a/mabmgr/mabmgr.h +++ b/mabmgr/mabmgr.h @@ -51,6 +51,11 @@ typedef struct radius_info_s { #define MABMGR_MAB_PORT_ENABLE_DEF DISABLE #define MABMGR_MAB_PORT_AUTH_TYPE_DEF AUTHMGR_PORT_MAB_AUTH_TYPE_EAP_MD5 +#define MABMGR_MAB_USER_CFG_ACCESS_TYPE_DEF "allow" /*CG_PAC*/ +#define MABMGR_MAB_USER_VLAN_ID_DEF 0 /*CG_PAC*/ +#define MABMGR_MAB_USER_SESSION_TIMEOUT_DEF 60 /*CG_PAC*/ +#define MABMGR_MAB_LAUTH_SUCCESS 1 /*CG_PAC*/ +#define MABMGR_MAB_LAUTH_FAILED 0 /*CG_PAC*/ /* MAB port config table param cache Info */ typedef struct mabPortConfigCacheParams_t { @@ -58,12 +63,50 @@ typedef struct mabPortConfigCacheParams_t { AUTHMGR_PORT_MAB_AUTH_TYPE_t mab_auth_type; } mabPortConfigCacheParams_t; +/* MAB User config table param cache Info */ +typedef struct mabUserConfigCacheParams_t { /*CG_PAC*/ + std::string access_type; /*allow list of the source mac. Default: “allow”*/ + int vlan_id; /*VLAN to be associated with the authorized client*/ + int session_timeout; /*Client session time*/ +} mabUserConfigCacheParams_t; + /* MAP to store MAB port config table params, * Key is "interface-id" (Eg. Ethernet0) * Value is "mabPortConfigCacheParams_t" */ typedef std::map mabPortConfigTableMap; +/*CG_PAC*/ +/*MAP to store MAB user configuration table parameters + * Key: MAC Address of Supplicant + * Value: mabUserConfigCacheParams_t + * */ +typedef std::map mabUserConfigTableMap; + +/*CG_PAC: attrInfo_t of ~/radius/radius_attr_parse.h */ +typedef struct lauth_attrInfo_s +{ + unsigned char userName[65]; + unsigned int userNameLen; + + //unsigned char serverState[SERVER_STATE_LEN]; + //unsigned int serverStateLen; + + //unsigned char serverClass[SERVER_CLASS_LEN]; + //unsigned int serverClassLen; + + unsigned int sessionTimeout; + //unsigned int terminationAction; + + //unsigned int accessLevel; + //unsigned char idFromServer; /* Most recent ID in EAP pkt received from Auth Server (0-255) */ + //unsigned char vlanString[RADIUS_VLAN_ASSIGNED_LEN+1]; + unsigned int vlanId; /* parsed VLAN id from vlan string */ + //unsigned int attrFlags; + //unsigned int vlanAttrFlags; + //bool rcvdEapAttr; +}lauth_attrInfo_t; + using namespace swss; using namespace std; @@ -73,15 +116,17 @@ class MabMgr MabMgr(DBConnector *configDb, DBConnector *stateDb, DBConnector *appDb); std::vector getSelectables(); bool processDbEvent(Selectable *source); - + int lauthClientChallengeProcess(string client_mac_key); /*CG_PAC*/ private: //tables this component listens to SubscriberStateTable m_confMabPortTbl; SubscriberStateTable m_confRadiusServerTable; SubscriberStateTable m_confRadiusGlobalTable; + SubscriberStateTable m_confMabUserCfgTbl; //CG_PAC radius_info_t m_radius_info; mabPortConfigTableMap m_mabPortConfigMap; + mabUserConfigTableMap m_mabUserConfigMap; //CG_PAC // DB Event handler functions bool processMabConfigPortTblEvent(Selectable *tbl); @@ -89,6 +134,9 @@ class MabMgr bool processRadiusGlobalTblEvent(Selectable *tbl); bool doMabPortTableSetTask(const KeyOpFieldsValuesTuple & t, uint32 & intIfNum); bool doMabPortTableDeleteTask(const KeyOpFieldsValuesTuple & t, uint32 & intIfNum); + bool processMabUserCfgTblEvent(Selectable *tbl); //CG_PAC + bool doMabUserCfgTableSetTask(const KeyOpFieldsValuesTuple & t); //CG_PAC + bool doMabUserCfgTableDeleteTask(const KeyOpFieldsValuesTuple & t); //CG_PAC void updateRadiusServer(); void updateRadiusServerGlobalKey(string newKey, string oldKey);