From c6582dd1c380f803101c33f74e12bddb3252bb14 Mon Sep 17 00:00:00 2001 From: Vijaya Kumar Abbaraju Date: Wed, 10 Apr 2024 02:26:52 -0700 Subject: [PATCH] MAB generic files --- src/sonic-pac/mab/mapping/mab_api.c | 373 +++++++++++++ src/sonic-pac/mab/mapping/mab_auth_mgr.c | 329 ++++++++++++ src/sonic-pac/mab/mapping/mab_cfg.c | 193 +++++++ src/sonic-pac/mab/mapping/mab_client.c | 266 ++++++++++ src/sonic-pac/mab/mapping/mab_debug.c | 64 +++ src/sonic-pac/mab/mapping/mab_ih.c | 640 +++++++++++++++++++++++ src/sonic-pac/mab/mapping/mab_init.c | 254 +++++++++ src/sonic-pac/mab/mapping/mab_socket.c | 462 ++++++++++++++++ 8 files changed, 2581 insertions(+) create mode 100755 src/sonic-pac/mab/mapping/mab_api.c create mode 100644 src/sonic-pac/mab/mapping/mab_auth_mgr.c create mode 100755 src/sonic-pac/mab/mapping/mab_cfg.c create mode 100755 src/sonic-pac/mab/mapping/mab_client.c create mode 100755 src/sonic-pac/mab/mapping/mab_debug.c create mode 100644 src/sonic-pac/mab/mapping/mab_ih.c create mode 100755 src/sonic-pac/mab/mapping/mab_init.c create mode 100644 src/sonic-pac/mab/mapping/mab_socket.c diff --git a/src/sonic-pac/mab/mapping/mab_api.c b/src/sonic-pac/mab/mapping/mab_api.c new file mode 100755 index 000000000000..fb8cefc6569c --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_api.c @@ -0,0 +1,373 @@ +/* + * Copyright 2024 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 "auth_mgr_api.h" +#include "mab_include.h" +#include "mab_vlan.h" +#include "mab_struct.h" + +extern mabBlock_t *mabBlock; + +/********************************************************************* +* @purpose Set the MAB value on the port. +* +* @param intIfNum @b{(input)} internal interface number +* @param mabEnable @b{(output)} boolean value determining if MAB +* has been configured on the port +* +* @returns SUCCESS +* @returns FAILURE +* @results REQUEST_DENIED if port control mode of the port is +* not mac-based +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabPortMABEnableSet(uint32 intIfNum, uint32 mabEnable) +{ + mabPortCfg_t *pCfg; + uint32 event = 0; + + if (mabIsValidIntf(intIfNum) != TRUE) + return FAILURE; + + if (mabIntfIsConfigurable(intIfNum, &pCfg) != TRUE) + return FAILURE; + + if (mabEnable != ENABLE && mabEnable != DISABLE) + return FAILURE; + + if (mabEnable == ENABLE) + { + pCfg->mabEnabled = ENABLE; + event = mabMgmtPortMABEnableSet; + } + else + { + pCfg->mabEnabled = DISABLE; + event = mabMgmtPortMABDisableSet; + } + pCfg->mabAuthType = FD_MAB_PORT_MAB_AUTH_TYPE; + + return mabIssueCmd(event, intIfNum, &mabEnable);; +} + +/********************************************************************* +* @purpose Get the operational MAB value on the port. +* +* @param intIfNum @b{(input)} internal interface number +* @param mabEnable @b{(output)} value determining if MAB +* has been operationally +* enabled on the port +* +* @returns SUCCESS +* @returns FAILURE +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabPortOperMABEnabledGet(uint32 intIfNum, uint32 *mabEnable) +{ + if (mabIsValidIntf(intIfNum) != TRUE) + return FAILURE; + + *mabEnable = mabBlock->mabPortInfo[intIfNum].mabEnabled; + + return SUCCESS; +} + +/********************************************************************* +* @purpose Set the authentication type on the port to be used by MAB. +* +* @param intIfNum @b{(input)} internal interface number +* @param auth_type @b{(input)} Authentication type {EAP-MD5 or PAP} +* +* @returns SUCCESS if able to set the auth_type successfully +* @results REQUEST_DENIED if MAB is not enabled on that port +* @returns FAILURE otherwise +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabPortMABAuthTypeSet(uint32 intIfNum, + AUTHMGR_PORT_MAB_AUTH_TYPE_t auth_type) +{ + mabPortCfg_t *pCfg = NULLPTR; + + if (( AUTHMGR_PORT_MAB_AUTH_TYPE_INVALID >= auth_type) || + ( AUTHMGR_PORT_MAB_AUTH_TYPE_LAST <= auth_type)) + { + /* Invalid input arguments */ + return FAILURE; + } + + if ( TRUE != mabIsValidIntf(intIfNum)) + { + return FAILURE; + } + + if (( TRUE != mabIntfIsConfigurable(intIfNum, &pCfg)) || + ( NULLPTR == pCfg)) + { + return FAILURE; + } + + /* check if MAB has been configured for the port */ + if ( ENABLE != pCfg->mabEnabled) + { + return REQUEST_DENIED; + } + + pCfg->mabAuthType = auth_type; + return SUCCESS; +} + +/********************************************************************* +* @purpose Determine if the interface is valid to participate in mab +* +* @param intIfNum @b{(input)} internal interface number +* +* @returns TRUE +* @returns FALSE +* +* @comments +* +* @end +*********************************************************************/ + BOOL mabIsValidIntf(uint32 intIfNum) +{ + INTF_TYPES_t sysIntfType; + + if ((nimGetIntfType(intIfNum, &sysIntfType) != SUCCESS) || + (mabIsValidIntfType(sysIntfType) != TRUE)) + { + return FALSE; + } + + return TRUE; +} + +/********************************************************************* +* @purpose Determine if the interface type is valid to participate in mab +* +* @param sysIntfType @b{(input)} interface type +* +* @returns TRUE +* @returns FALSE +* +* @comments +* +* @end +*********************************************************************/ + BOOL mabIsValidIntfType(uint32 sysIntfType) +{ + if (sysIntfType != PHYSICAL_INTF) + return FALSE; + + return TRUE; +} + +/********************************************************************* +* @purpose Set port control mode +* +* @param intIfNum @b{(input)} internal interface number +* @param portControl @b{(input)} port control mode +* +* @returns SUCCESS +* @returns FAILURE +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabPortControlModeSet(uint32 intIfNum, AUTHMGR_PORT_CONTROL_t portControl) +{ + mabPortCfg_t *pCfg; + + if (mabIsValidIntf(intIfNum) != TRUE) + return FAILURE; + + if (mabIntfIsConfigurable(intIfNum, &pCfg) != TRUE) + return FAILURE; + + return mabIssueCmd(mabMgmtPortControlModeSet, intIfNum, &portControl); +} + +/********************************************************************* +* @purpose Set host control mode +* +* @param intIfNum @b{(input)} internal interface number +* @param hostControl @b{(input)} host control mode +* +* @returns SUCCESS +* @returns FAILURE +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabPortControlHostModeSet(uint32 intIfNum, AUTHMGR_HOST_CONTROL_t hostMode) +{ + mabPortCfg_t *pCfg; + + if (mabIsValidIntf(intIfNum) != TRUE) + return FAILURE; + + if (mabIntfIsConfigurable(intIfNum, &pCfg) != TRUE) + return FAILURE; + + return mabIssueCmd(mabMgmtPortHostModeSet, intIfNum, &hostMode); +} + +/********************************************************************* +* @purpose Return Internal Interface Number of the first valid interface for +* mab. +* +* @param pFirstIntIfNum @b{(output)} pointer to first internal interface number +* +* @returns SUCCESS if success +* @returns ERROR if interface does not exist +* @returns FAILURE if other failure +* +* @comments none +* +* @end +*********************************************************************/ +RC_t mabFirstValidIntfNumber(uint32 *pFirstIntIfNum) +{ + RC_t rc = FAILURE; + nimUSP_t usp; + uint32 intIfNum = NULL; + + if ( SUCCESS == nimFirstValidIntfNumberByType( PHYSICAL_INTF, &intIfNum)) + { + memset(&usp, 0, sizeof(usp)); + if (( SUCCESS == nimGetUnitSlotPort(intIfNum, &usp))) + { + rc = mabNextValidIntf(intIfNum, &intIfNum); + } + else + { + rc = SUCCESS; + } + + if ( SUCCESS == rc) + { + /* Copy the valid interface in the output pointer */ + *pFirstIntIfNum = intIfNum; + } + } + return rc; +} + +/********************************************************************* +* @purpose Return Internal Interface Number of next valid interface for +* mab. +* +* @param intIfNum @b{(input)} Internal Interface Number +* @param pNextintIfNum @b{(output)} pointer to Next Internal Interface Number, +* +* @returns SUCCESS if success +* @returns ERROR if interface does not exist +* @returns FAILURE if other failure +* +* @comments none +* +* @end +*********************************************************************/ +RC_t mabNextValidIntf(uint32 intIfNum, uint32 *pNextIntIfNum) +{ + RC_t rc = FAILURE; + nimUSP_t usp; + uint32 nextIntIfNum = intIfNum; + + while ( SUCCESS == nimNextValidIntfNumberByType( PHYSICAL_INTF, nextIntIfNum, &nextIntIfNum)) + { + memset(&usp, 0, sizeof(usp)); + if ( SUCCESS == nimGetUnitSlotPort(nextIntIfNum, &usp)) + { + /* Next mab valid interface found. */ + *pNextIntIfNum = nextIntIfNum; + rc = SUCCESS; + break; + } + } + + return rc; + +} + +/********************************************************************* +* @purpose Update the RADIUS server configuration +* +* @param add @b{(input)} whether server should be added or deleted +* @param radius_type @b{(input)} radius server type +* @param serv_addr @b{(input)} radius server address +* @param serv_priority @b{(input)} radius server priority +* @param radius_key @b{(input)} radius server key +* @param serv_port @b{(input)} radius server port +* +* @returns SUCCESS values are valid and are updated successfully +* @returns FAILURE otherwise +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabRadiusServerUpdate(uint32 cmd, const char *radius_type, + const char *serv_addr, const char *serv_priority, + const char *radius_key, const char *serv_port) +{ + mabRadiusServer_t msg; + RC_t rc = SUCCESS; + + memset(&msg, 0, sizeof(msg)); + + msg.cmd = cmd; + + if (radius_type) + strncpy(msg.cmd_data.server.radius_type, radius_type, sizeof(msg.cmd_data.server.radius_type)-1); + + if (serv_addr) + strncpy(msg.cmd_data.server.serv_addr, serv_addr, sizeof(msg.cmd_data.server.serv_addr)-1); + + if (serv_port) + { + strncpy(msg.cmd_data.server.serv_port, serv_port, sizeof(msg.cmd_data.server.serv_port)-1); + MAB_EVENT_TRACE("%s: cfg update for server %s port %s", __FUNCTION__, serv_addr, serv_port); + } + + if (serv_priority) + { + strncpy(msg.cmd_data.server.serv_priority, serv_priority, sizeof(msg.cmd_data.server.serv_priority)-1); + MAB_EVENT_TRACE("%s: cfg update for server %s priority %s", __FUNCTION__, serv_addr, serv_priority); + } + + if (radius_key) + { + strncpy(msg.cmd_data.server.key.key, radius_key, sizeof(msg.cmd_data.server.key.key)-1); + msg.cmd_data.server.key.key_len = strlen(radius_key); + MAB_EVENT_TRACE("%s: cfg update for server %s key len %d", __FUNCTION__, serv_addr, (unsigned int)strlen(radius_key)); + } + + rc = mabIssueCmd(mabRadiusConfigUpdate, 0, &msg); + + MAB_EVENT_TRACE("%s:Sent cfg update for server %s rc = %d", __FUNCTION__, serv_addr, rc); + return rc; +} diff --git a/src/sonic-pac/mab/mapping/mab_auth_mgr.c b/src/sonic-pac/mab/mapping/mab_auth_mgr.c new file mode 100644 index 000000000000..df15ceb8db06 --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_auth_mgr.c @@ -0,0 +1,329 @@ +/* + * Copyright 2024 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 "includes.h" +#include "pacinfra_common.h" +#include "mab_include.h" +#include "radius_attr_parse.h" +#include "packet.h" +#include "auth_mgr_exports.h" +#include "fpSonicUtils.h" + +#define STATUS_COPY(_status) static void _status##_##copy(char *intf, clientStatusReply_t *reply, char *addr, void *param) +#define STATUS_ENTER(_status, _intf, _reply, _addr, _param) _status##_##copy(_intf, _reply, _addr, _param) +#define ETHERNET_PREFIX "Ethernet" + +#define STATUS_MALLOC(__status, __data, _reply) \ + do { \ + reply = (clientStatusReply_t *)malloc(sizeof(*_reply)); \ + memset(_reply, 0, sizeof(*_reply)); \ + } while(0); + + +typedef struct status_map_s +{ + char *status; + unsigned int val; +}status_map_t; + +static int mab_data_async_send (char *buf, int bufLen, unsigned char *addr) +{ + struct sockaddr_in saddr; + int fd, ret_val; + struct hostent *local_host; /* need netdb.h for this */ + int i; + char *ptr = buf; + struct linger sl; + struct sockaddr_in client; + socklen_t clientlen = sizeof(client); + + printf("buffer: "); + for (i =0; i<10; i++) + { + printf("0x%x ", ptr[i]); + } + printf("\n"); + + /* Step1: create a TCP socket */ + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + { + fprintf(stderr, "socket failed [%s]\n", strerror(errno)); + return -1; + } + + MAB_EVENT_TRACE( + "Created a socket with fd: %d", fd); + + /* Let us initialize the server address structure */ + saddr.sin_family = AF_INET; + saddr.sin_port = htons(3434); + local_host = gethostbyname("127.0.0.1"); + saddr.sin_addr = *((struct in_addr *)local_host->h_addr); + + /* Step2: connect to the server socket */ + ret_val = connect(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); + if (ret_val == -1) + { + fprintf(stderr, "connect failed [%s]\n", strerror(errno)); + close(fd); + return -1; + } + getsockname(fd, (struct sockaddr *) &client, &clientlen); + + if (addr) + { + MAB_EVENT_TRACE( + " The Socket is now connected fd %d [%s:%u]" + " mac (%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x)", + fd, inet_ntoa(client.sin_addr), ntohs(client.sin_port), + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + } + else + { + MAB_EVENT_TRACE( + "The Socket is now connected fd %d [%s:%u] ", + fd, inet_ntoa(client.sin_addr), ntohs(client.sin_port)); + } + + sl.l_onoff = 1; /* enable linger option */ + sl.l_linger = 30; /* timeout interval in seconds */ + if (-1 == setsockopt(fd, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl))) + { + MAB_EVENT_TRACE( + "unable to set SO_LINGER option socket with fd: %d", fd); + } + + /* Next step: send some data */ + ret_val = send(fd, buf, bufLen, 0); + MAB_EVENT_TRACE( + "fd : %d Successfully sent data (len %d bytes): %s", + fd, bufLen, buf); + + /* Last step: close the socket */ + close(fd); + return 0; +} + +STATUS_COPY(AUTH_SUCCESS) +{ + authmgrClientStatusInfo_t *clientInfo = (authmgrClientStatusInfo_t *)param; + memset(reply, 0, sizeof(*reply)); + + if (addr) + { + memcpy(reply->info.authInfo.addr, addr, 6); + } + strncpy (reply->method, "mab", sizeof(reply->method)-1); + reply->status = AUTH_SUCCESS; + strncpy (reply->intf, intf, sizeof(reply->intf)-1); + + /* copy user details */ + memcpy(reply->info.authInfo.userName, clientInfo->info.authInfo.authmgrUserName, + min(sizeof(clientInfo->info.authInfo.authmgrUserName), sizeof(clientInfo->info.authInfo.authmgrUserName))); + reply->info.authInfo.userNameLength = strlen(clientInfo->info.authInfo.authmgrUserName); + + /* copy bam used for authentication */ + strncpy(reply->info.authInfo.bam_used, "radius", sizeof(reply->info.authInfo.bam_used)-1); + + /* copy all the attributes received from radius/ or backend method */ + memcpy(&reply->info.authInfo.attrInfo, &clientInfo->info.authInfo.attrInfo, sizeof(attrInfo_t)); +} + + + +STATUS_COPY(AUTH_FAIL) +{ + authmgrClientStatusInfo_t *clientInfo = (authmgrClientStatusInfo_t *)param; + + memset(reply, 0, sizeof(*reply)); + if (addr) + { + memcpy(reply->info.authInfo.addr, addr, 6); + } + strncpy (reply->method, "mab", sizeof(reply->method)-1); + reply->status = AUTH_FAIL; + strncpy (reply->intf, intf, sizeof(reply->intf)-1); + + /* copy user details */ + memcpy(reply->info.authInfo.userName, clientInfo->info.authInfo.authmgrUserName, + min(sizeof(clientInfo->info.authInfo.authmgrUserName), sizeof(clientInfo->info.authInfo.authmgrUserName))); + reply->info.authInfo.userNameLength = strlen(clientInfo->info.authInfo.authmgrUserName); +} + + +STATUS_COPY(AUTH_TIMEOUT) +{ + authmgrClientStatusInfo_t *clientInfo = (authmgrClientStatusInfo_t *)param; + + memset(reply, 0, sizeof(*reply)); + if (addr) + { + memcpy(reply->info.authInfo.addr, addr, 6); + } + strncpy (reply->method, "mab", sizeof(reply->method)-1); + reply->status = AUTH_TIMEOUT; + strncpy (reply->intf, intf, sizeof(reply->intf)-1); + + /* copy user details */ + memcpy(reply->info.authInfo.userName, clientInfo->info.authInfo.authmgrUserName, + min(sizeof(clientInfo->info.authInfo.authmgrUserName), sizeof(clientInfo->info.authInfo.authmgrUserName))); + reply->info.authInfo.userNameLength = strlen(clientInfo->info.authInfo.authmgrUserName); +} + + +STATUS_COPY(AUTH_SERVER_COMM_FAILURE) +{ + authmgrClientStatusInfo_t *clientInfo = (authmgrClientStatusInfo_t *)param; + + memset(reply, 0, sizeof(*reply)); + if (addr) + { + memcpy(reply->info.authInfo.addr, addr, 6); + } + strncpy (reply->method, "mab", sizeof(reply->method)-1); + reply->status = AUTH_SERVER_COMM_FAILURE; + strncpy (reply->intf, intf, sizeof(reply->intf)-1); + + /* copy user details */ + memcpy(reply->info.authInfo.userName, clientInfo->info.authInfo.authmgrUserName, + min(sizeof(clientInfo->info.authInfo.authmgrUserName), sizeof(clientInfo->info.authInfo.authmgrUserName))); + reply->info.authInfo.userNameLength = strlen(clientInfo->info.authInfo.authmgrUserName); +} + + +STATUS_COPY(METHOD_CHANGE) +{ + authmgrClientStatusInfo_t *clientInfo = (authmgrClientStatusInfo_t *)param; + + memset(reply, 0, sizeof(*reply)); + if (addr) + { + memcpy(reply->info.authInfo.addr, addr, 6); + } + strncpy (reply->method, "mab", sizeof(reply->method)-1); + reply->status = METHOD_CHANGE; + + strncpy (reply->intf, intf, sizeof(reply->intf)-1); + + if (clientInfo->info.enableStatus) + { + strncpy (reply->info.enableStatus, "enable", strlen("enable")+1); + } + else + { + strncpy (reply->info.enableStatus, "disable", strlen("disable")+1); + } + +} + +STATUS_COPY(RADIUS_SERVERS_DEAD) +{ + authmgrClientStatusInfo_t *clientInfo = (authmgrClientStatusInfo_t *)param; + + memset(reply, 0, sizeof(*reply)); + if (addr) + { + memcpy(reply->info.authInfo.addr, addr, 6); + } + strncpy (reply->method, "mab", sizeof(reply->method)-1); + reply->status = RADIUS_SERVERS_DEAD; + strncpy (reply->intf, intf, sizeof(reply->intf)-1); + + /* copy user details */ + memcpy(reply->info.authInfo.userName, clientInfo->info.authInfo.authmgrUserName, + min(sizeof(clientInfo->info.authInfo.authmgrUserName), sizeof(clientInfo->info.authInfo.authmgrUserName))); + reply->info.authInfo.userNameLength = strlen(clientInfo->info.authInfo.authmgrUserName); +} + +static int client_resp_val_get(char *in) +{ + unsigned int i = 0; + + static status_map_t status_map[] = { + {"auth_fail", AUTH_FAIL}, + {"auth_success", AUTH_SUCCESS}, + {"auth_timeout", AUTH_TIMEOUT}, + {"auth_server_comm_failure", AUTH_SERVER_COMM_FAILURE}, + {"method_change", METHOD_CHANGE}, + {"radius_server_dead", RADIUS_SERVERS_DEAD}, + }; + + for (i = 0; i < sizeof(status_map)/sizeof(status_map_t); i++) + { + if (0 == strcmp(in, status_map[i].status)) + { + return status_map[i].val; + } + } + return -1; +} + +int mabPortClientAuthStatusUpdate(int intIfNum, unsigned char *addr, char *status, void *param) +{ + clientStatusReply_t *reply; + unsigned int val = 0; + char8 intf[ NIM_IF_ALIAS_SIZE + 1] = {}; + + fpGetHostIntfName(intIfNum, intf); + + val = client_resp_val_get(status); + + STATUS_MALLOC(val, param, reply); + + switch (val) + { + case AUTH_FAIL: + STATUS_ENTER(AUTH_FAIL, intf, reply, addr, param); + break; + + case AUTH_SUCCESS: + STATUS_ENTER(AUTH_SUCCESS, intf, reply, addr, param); + break; + + case AUTH_TIMEOUT: + STATUS_ENTER(AUTH_TIMEOUT, intf, reply, addr, param); + break; + + case AUTH_SERVER_COMM_FAILURE: + STATUS_ENTER(AUTH_SERVER_COMM_FAILURE, intf, reply, addr, param); + break; + + case METHOD_CHANGE: + STATUS_ENTER(METHOD_CHANGE, intf, reply, addr, param); + break; + + case RADIUS_SERVERS_DEAD: + STATUS_ENTER(RADIUS_SERVERS_DEAD, intf, reply, addr, param); + break; + + default: + /* unknown response is received */ + return -1; + + } + + /* send msg */ + mab_data_async_send((char *)reply, sizeof(*reply), addr); + + if (reply) + free (reply); + return 0; +} + + diff --git a/src/sonic-pac/mab/mapping/mab_cfg.c b/src/sonic-pac/mab/mapping/mab_cfg.c new file mode 100755 index 000000000000..cc12f1212114 --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_cfg.c @@ -0,0 +1,193 @@ +/* + * Copyright 2024 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 "mab_include.h" +#include "mab_client.h" +#include "mab_timer.h" +#include "mab_struct.h" +#include "mab_debug.h" + +extern mabBlock_t *mabBlock; + +/********************************************************************* +* @purpose Get the physical port for the logical interface +* +* @param intIfNum @b{(input)) internal interface number +* +* @returns end index for specified interface in mab logical +* interface list +* +* @comments +* +* @end +*********************************************************************/ +uint32 mabPhysPortGet(uint32 lIntIfNum) +{ + uint32 physPort; + MAB_PORT_GET(physPort, lIntIfNum); + return physPort; +} + +/********************************************************************* +* @purpose Build default mab config data +* +* @param ver @((input)) Software version of Config Data +* +* @returns void +* +* @comments +* +* @end +*********************************************************************/ +void mabBuildDefaultConfigData() +{ + uint32 cfgIndex; + nimConfigID_t configId[ MAB_INTF_MAX_COUNT]; + + /* Save the config IDs */ + memset((void *)&configId[0], 0, sizeof(nimConfigID_t) * MAB_INTF_MAX_COUNT); + + for (cfgIndex = 1; cfgIndex < MAB_INTF_MAX_COUNT; cfgIndex++) + NIM_CONFIG_ID_COPY(&configId[cfgIndex], &mabBlock->mabCfg->mabPortCfg[cfgIndex].configId); + + memset((void *)mabBlock->mabCfg, 0, sizeof(mabCfg_t)); + + for (cfgIndex = 1; cfgIndex < MAB_INTF_MAX_COUNT; cfgIndex++) + { + mabBuildDefaultIntfConfigData(&configId[cfgIndex], &mabBlock->mabCfg->mabPortCfg[cfgIndex]); + } + return; +} + +/********************************************************************* +* @purpose Build default mab port config data +* +* @parms config Id, the config Id to be placed into the intf config +* @parms pCfg, a pointer to the interface structure +* +* @returns none +* +* +* @end +*********************************************************************/ +void mabBuildDefaultIntfConfigData(nimConfigID_t *configId, mabPortCfg_t *pCfg) +{ + pCfg->mabEnabled = FD_MAB_PORT_MAB_ENABLED; + pCfg->mabAuthType = FD_MAB_PORT_MAB_AUTH_TYPE; +} + +/********************************************************************* +* @purpose Apply mab config data +* +* @param void +* +* @returns SUCCESS +* @returns FAILURE +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabApplyConfigData(void) +{ + return (mabIssueCmd(mabMgmtApplyConfigData, NULL, NULLPTR)); +} + +/********************************************************************* +* @purpose Fill in default values and set the port state +* +* @param intIfNum @b{(input)) internal interface number +* +* @returns SUCCESS +* @returns FAILURE +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabPortReset(uint32 intIfNum) +{ + mabPortInfoInitialize(intIfNum, FALSE); + return SUCCESS; +} + +/********************************************************************* +* @purpose Initialize the Dot1x Port Structure with Default Values +* +* @param intIfNum @b{(input)) internal interface number +* +* @returns SUCCESS +* @returns FAILURE +* +* @comments +* +* @end +*********************************************************************/ +RC_t mabPortInfoInitialize(uint32 intIfNum, BOOL flag) +{ + mabPortCfg_t *pCfg; + uint32 linkState = 0, adminState = 0; + + if (mabIntfIsConfigurable(intIfNum, &pCfg) != TRUE) + return SUCCESS; + + memset(&mabBlock->mabPortInfo[intIfNum], 0, sizeof(mabPortInfo_t)); + + (void)osapiWriteLockGive(mabBlock->mabRWLock); + + + (void)osapiWriteLockTake(mabBlock->mabRWLock, WAIT_FOREVER); + + mabAppTimerDeInitCheck(); + + mabBlock->mabPortInfo[intIfNum].portControlMode = AUTHMGR_PORT_AUTO; + mabBlock->mabPortInfo[intIfNum].hostMode = AUTHMGR_MULTI_AUTH_MODE; + + mabBlock->mabPortInfo[intIfNum].maxUsers = MAB_MAX_USERS_PER_PORT; + mabBlock->mabPortInfo[intIfNum].numUsers = 0; + + mabBlock->mabPortInfo[intIfNum].currentId = 0; + mabBlock->mabPortInfo[intIfNum].initialize = FALSE; + + if ( (nimGetIntfLinkState(intIfNum, &linkState) == SUCCESS) && (linkState == UP) && + (nimGetIntfAdminState(intIfNum, &adminState) == SUCCESS) && (adminState == ENABLE) ) + { + mabBlock->mabPortInfo[intIfNum].portEnabled = TRUE; + mabBlock->mabPortInfo[intIfNum].mabEnabled = pCfg->mabEnabled; + } + else + { + mabBlock->mabPortInfo[intIfNum].portEnabled = FALSE; + mabBlock->mabPortInfo[intIfNum].mabEnabled = DISABLE; + } + + if ( ENABLE == mabBlock->mabPortInfo[intIfNum].mabEnabled) + { + /* Register for time ticks with appTimer */ + if ( NULLPTR == mabBlock->mabTimerCB) + { + mabBlock->mabTimerCB = appTimerInit( MAB_COMPONENT_ID, mabTimerExpiryHdlr, + NULLPTR, APP_TMR_1SEC, mabBlock->mabAppTimerBufferPoolId); + } + } + + mabBlock->mabPortInfo[intIfNum].authCount = 0; + + /* Copy config data into operational data */ + mabBlock->mabPortInfo[intIfNum].maxUsers = AUTHMGR_PORT_MAX_MAC_USERS; + + return SUCCESS; +} diff --git a/src/sonic-pac/mab/mapping/mab_client.c b/src/sonic-pac/mab/mapping/mab_client.c new file mode 100755 index 000000000000..f4cb6684f15e --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_client.c @@ -0,0 +1,266 @@ +/* + * Copyright 2024 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 "mab_include.h" +#include "mab_client.h" +#include "mab_timer.h" +#include "mab_struct.h" + +extern mabBlock_t *mabBlock; + +/********************************************************************* + * @purpose Set the mab client authorization status + * + * @param lIntIfNum @b{(input)) internal interface number + * @param portStatus @b{(input)) port authorization status setting + * + * @returns SUCCESS + * @returns FAILURE + * @returns ERROR + * + * @comments none + * + * @end + *********************************************************************/ +RC_t mabClientStatusSet(mabLogicalPortInfo_t *logicalPortInfo, AUTHMGR_PORT_STATUS_t portStatus) +{ + uint32 physPort = 0, lPort = 0, type = 0; + + MAB_IF_NULLPTR_RETURN_LOG(logicalPortInfo); + + MAB_LPORT_KEY_UNPACK(physPort, lPort, type, logicalPortInfo->key.keyNum); + + MAB_EVENT_TRACE("%s:Setting the Logical port-%d to %s\n", + __FUNCTION__, logicalPortInfo->key.keyNum, + (portStatus== AUTHMGR_PORT_STATUS_AUTHORIZED)?"Authorize":"Unauthorize"); + + /* Verify port status parm value */ + if (portStatus != AUTHMGR_PORT_STATUS_AUTHORIZED && portStatus != AUTHMGR_PORT_STATUS_UNAUTHORIZED) + return FAILURE; + + /*If setting to the same value, just return success */ + if (portStatus == logicalPortInfo->client.logicalPortStatus) + { + MAB_EVENT_TRACE("%s:%d Status already set \n",__FUNCTION__,__LINE__); + return SUCCESS; + } + + if ((( AUTHMGR_PORT_FORCE_UNAUTHORIZED == mabBlock->mabPortInfo[physPort].portControlMode) && + ( AUTHMGR_PORT_STATUS_AUTHORIZED == portStatus)) || + (( AUTHMGR_PORT_FORCE_AUTHORIZED == mabBlock->mabPortInfo[physPort].portControlMode) && + ( AUTHMGR_PORT_STATUS_UNAUTHORIZED == portStatus))) + { + /* this combination is not allowed.. So just a sanity check */ + return FAILURE; + } + + /* */ + + logicalPortInfo->client.logicalPortStatus = portStatus; + + if ( AUTHMGR_PORT_STATUS_AUTHORIZED == portStatus) + { + /* set the port status to authorized */ + mabBlock->mabPortInfo[physPort].authCount++; + } + else + { + if (mabBlock->mabPortInfo[physPort].authCount > 0) + { + mabBlock->mabPortInfo[physPort].authCount--; + } + } + return SUCCESS; +} + +/********************************************************************* + * @purpose function to cleanup the client sw info + * + * @param intIfNum @b{(input)) internal interface number + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments + * + * @end + *********************************************************************/ +RC_t mabClientSwInfoCleanup(mabLogicalPortInfo_t *logicalPortInfo) +{ + RC_t rc = SUCCESS, rc1 = SUCCESS, rc2 = SUCCESS, rc3 = SUCCESS; + mabPortCfg_t *pCfg; + uint32 physPort = 0, lPort = 0, type = 0; + enetMacAddr_t nullMacAddr; + + memset(&nullMacAddr.addr,0, ENET_MAC_ADDR_LEN); + + MAB_IF_NULLPTR_RETURN_LOG(logicalPortInfo); + + MAB_LPORT_KEY_UNPACK(physPort, lPort, type, logicalPortInfo->key.keyNum); + + + if (mabIntfIsConfigurable(physPort, &pCfg) != TRUE) + return SUCCESS; + + /* delete the timers if any */ + rc = mabTimerDestroy(mabBlock->mabTimerCB, logicalPortInfo); + + /* set the client to un-authorized */ + + rc1 = mabClientStatusSet(logicalPortInfo, AUTHMGR_PORT_STATUS_UNAUTHORIZED); + + /*remove supplicant mac address from Mac address Database*/ + /*input check*/ + if (0 != memcmp(logicalPortInfo->client.suppMacAddr.addr, nullMacAddr.addr, ENET_MAC_ADDR_LEN)) + { + rc2 = mabMacAddrInfoRemove(&(logicalPortInfo->client.suppMacAddr)); + } + + if(mabBlock->mabPortInfo[physPort].numUsers > 0) + { + mabBlock->mabPortInfo[physPort].numUsers--; + } + + /* Deallocate memory for Clients */ + rc3 = mabLogicalPortInfoDeAlloc(logicalPortInfo); + + if (( SUCCESS != rc) || + ( SUCCESS != rc1) || + ( SUCCESS != rc2) || + ( SUCCESS != rc3)) + { + MAB_EVENT_TRACE("%s:%d rc %d, rc1 %d rc2 %d, rc3 %d \n", + __FUNCTION__,__LINE__, rc, rc1, rc2, rc3); + return FAILURE; + } + else + { + return SUCCESS; + } +} + +/********************************************************************* + * @purpose function to check and deAllocate the client + * + * @param intIfNum @b{(input)) internal interface number + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments + * + * @end + *********************************************************************/ +RC_t mabClientDisconnectAction(mabLogicalPortInfo_t *logicalPortInfo) +{ + RC_t rc = SUCCESS; + mabPortCfg_t *pCfg; + uint32 physPort = 0, lPort = 0, type = 0; + BOOL valid = FALSE; + + MAB_IF_NULLPTR_RETURN_LOG(logicalPortInfo); + + MAB_LPORT_KEY_UNPACK(physPort, lPort, type, logicalPortInfo->key.keyNum); + + if (mabIntfIsConfigurable(physPort, &pCfg) != TRUE) + return SUCCESS; + + /* check if the client can be de-allocated */ + + MAB_EVENT_TRACE("checking if logicalInterface %d can be disconnected\n", logicalPortInfo->key.keyNum); + + if (logicalPortInfo->client.reAuthenticate) + { + MAB_EVENT_TRACE("%s:%d reAuthenticate = %d \n", + __FUNCTION__,__LINE__, logicalPortInfo->client.reAuthenticate); + return FAILURE; + } + + if (( FALSE == logicalPortInfo->protocol.authSuccess) && + ( FALSE == logicalPortInfo->protocol.authFail)) + { + /* node just allocated */ + MAB_EVENT_TRACE( + "%s:%d node just allocated \n", + __FUNCTION__,__LINE__); + return FAILURE; + } + + if ( SUCCESS == mabHostIsDynamicNodeAllocCheck(mabBlock->mabPortInfo[physPort].hostMode, &valid)) + { + if (valid) + { + MAB_EVENT_TRACE( + "logicalInterface %d is getting disconnected\n", logicalPortInfo->key.keyNum); + rc = mabClientSwInfoCleanup(logicalPortInfo); + } + else + { + return FAILURE; + } + } + + if ( SUCCESS != rc) + { + MAB_EVENT_TRACE( + "%s:%d Failure in Disconnect Action\n", + __FUNCTION__, __LINE__); + } + + return rc; +} + +/********************************************************************* + * @purpose function to cleanup the client + * + * @param intIfNum @b{(input)) internal interface number + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments + * + * @end + *********************************************************************/ +RC_t mabClientInfoCleanup(mabLogicalPortInfo_t *logicalPortInfo) +{ + RC_t rc = SUCCESS; + mabPortCfg_t *pCfg; + uint32 physPort = 0, lPort = 0, type = 0; + + MAB_IF_NULLPTR_RETURN_LOG(logicalPortInfo); + + MAB_LPORT_KEY_UNPACK(physPort, lPort, type, logicalPortInfo->key.keyNum); + + + if (mabIntfIsConfigurable(physPort, &pCfg) != TRUE) + return SUCCESS; + + if ( SUCCESS == rc) + rc = mabClientSwInfoCleanup(logicalPortInfo); + + if ( SUCCESS != rc) + { + MAB_EVENT_TRACE( + "%s:%d Failure in client cleanup \n", + __FUNCTION__, __LINE__); + } + + return rc; +} + + diff --git a/src/sonic-pac/mab/mapping/mab_debug.c b/src/sonic-pac/mab/mapping/mab_debug.c new file mode 100755 index 000000000000..44ceb3945d70 --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_debug.c @@ -0,0 +1,64 @@ +/* + * Copyright 2024 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 "mab_include.h" +#include "mab_struct.h" +#include "auth_mgr_exports.h" + +extern mabBlock_t *mabBlock; + +char *mabHostModeStringGet( AUTHMGR_HOST_CONTROL_t hostMode) +{ + switch (hostMode) + { + case AUTHMGR_SINGLE_AUTH_MODE:return "MAB_SINGLE_AUTH_MODE"; + case AUTHMGR_MULTI_HOST_MODE:return "MAB_MULTI_HOST_MODE"; + case AUTHMGR_MULTI_AUTH_MODE:return "MAB_MULTI_AUTH_MODE"; + default: return "Unknown host mode"; + } +} + +char *mabNodeTypeStringGet(authmgrNodeType_t type) +{ + switch (type) + { + case AUTHMGR_PHYSICAL:return "AUTHMGR_PHYSICAL"; + case AUTHMGR_LOGICAL:return "AUTHMGR_LOGICAL"; + default: return "Undefined"; + } +} + +char *mabTimerTypeStringGet(mabTimerType_t type) +{ + switch (type) + { + case MAB_SERVER_AWHILE:return "MAB_SERVER_AWHILE"; + default: return "Undefined"; + } +} + +char *mabVlanTypeStringGet(authmgrVlanType_t type) +{ + switch (type) + { + case AUTHMGR_VLAN_RADIUS:return "AUTHMGR_VLAN_RADIUS"; + case AUTHMGR_VLAN_GUEST:return "AUTHMGR_VLAN_GUEST"; + case AUTHMGR_VLAN_UNAUTH:return "AUTHMGR_VLAN_UNAUTH"; + case AUTHMGR_VLAN_DEFAULT:return "AUTHMGR_VLAN_DEFAULT"; + case AUTHMGR_VLAN_BLOCKED:return "AUTHMGR_VLAN_BLOCKED"; + default: return "Undefined"; + } +} diff --git a/src/sonic-pac/mab/mapping/mab_ih.c b/src/sonic-pac/mab/mapping/mab_ih.c new file mode 100644 index 000000000000..565af259a7c5 --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_ih.c @@ -0,0 +1,640 @@ +/* + * Copyright 2024 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 "mab_include.h" +#include "mab_db.h" +#include "mab_client.h" +#include "mab_struct.h" + +extern mabBlock_t *mabBlock; + +extern void mabWarmRestartTypeSet( BOOL FALSE); + +/********************************************************************* + * @purpose Handles events generated by NIM + * + * @param intIfNum @b{(input)) internal interface number + * @param intfEvent @b{(input)) interface event + * @param correlator @b{(input)) Correlator for the event + * @param eventData @b((input)) Additional event specific data + * + * @returns SUCCESS on a successful operation + * @returns FAILURE for any error + * + * @comments + * + * @end + *********************************************************************/ +RC_t mabIntfChangeCallback(uint32 intIfNum, uint32 intfEvent, + NIM_CORRELATOR_t correlator, + NIM_EVENT_SPECIFIC_DATA_t eventData) +{ + mabIntfChangeParms_t parms; + + parms.intfEvent = intfEvent; + parms.nimCorrelator = correlator; + + return mabIssueCmd(mabIntfChange, intIfNum, &parms); +} + +/********************************************************************* + * @purpose Handles startup notification from NIM + * + * @param intIfNum @b{(input)) internal interface number + * @param intfEvent @b{(input)) interface event + * @param correlator @b{(input)) Correlator for the event + * + * @returns SUCCESS on a successful operation + * @returns FAILURE for any error + * + * @comments + * + * @end + *********************************************************************/ +void mabIntfStartupCallback(NIM_STARTUP_PHASE_t startupPhase) +{ + /* hold NIM till MAB is ready */ + while (!(MAB_IS_READY)) + { + LOGF( LOG_SEVERITY_ERROR, + "Received an interface startup callback while MAB is not ready(startup phase=%d). waiting..", + startupPhase); + osapiSleep(1); + } + mabIssueCmd(mabIntfStartup, NULL, &startupPhase); + return; +} + +/********************************************************************* + * @purpose Process NIM startup callback + * + * @param startupPhase @b{(input)) CREATE or ACTIVATE + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments none + * + * @end + *********************************************************************/ +RC_t mabIhProcessIntfStartup(NIM_STARTUP_PHASE_t startup_phase) +{ + RC_t rc; + uint32 intIfNum = 0; + PORTEVENT_MASK_t nimEventMask; + uint32 startTime, endTime; + uchar8 ifName[ NIM_IF_ALIAS_SIZE + 1]; + + + MAB_EVENT_TRACE("%s:%d Received event %d from NIM and warm restart %d \n", + __FUNCTION__,__LINE__,startup_phase,mabIsRestartTypeWarm()); + + startTime = osapiTimeMillisecondsGet(); + switch (startup_phase) + { + case NIM_INTERFACE_CREATE_STARTUP: + rc = nimFirstValidIntfNumber(&intIfNum); + + while (rc == SUCCESS) + { + if (mabIsValidIntf(intIfNum) == TRUE) + { + if (mabIntfCreate(intIfNum) != SUCCESS) + { + nimGetIntfName(intIfNum, ALIASNAME, ifName); + LOGF( LOG_SEVERITY_ERROR, + "Error in creating interface %s.", ifName); + } + } + rc = nimNextValidIntfNumber(intIfNum, &intIfNum); + } + + /* Now ask NIM to send any future changes for these event types */ + memset(&nimEventMask, 0, sizeof(PORTEVENT_MASK_t)); + PORTEVENT_SETMASKBIT(nimEventMask, CREATE); + PORTEVENT_SETMASKBIT(nimEventMask, DELETE); + nimRegisterIntfEvents( MAB_COMPONENT_ID, nimEventMask); + break; + + case NIM_INTERFACE_ACTIVATE_STARTUP: + + + + rc = mabIntfActivateStartup(); + + + /* Now ask NIM to send any future changes for these event types */ + memset(&nimEventMask, 0, sizeof(PORTEVENT_MASK_t)); + PORTEVENT_SETMASKBIT(nimEventMask, CREATE); + PORTEVENT_SETMASKBIT(nimEventMask, DELETE); + PORTEVENT_SETMASKBIT(nimEventMask, ATTACH); + PORTEVENT_SETMASKBIT(nimEventMask, DETACH); + PORTEVENT_SETMASKBIT(nimEventMask, PORT_ENABLE); + PORTEVENT_SETMASKBIT(nimEventMask, PORT_DISABLE); + PORTEVENT_SETMASKBIT(nimEventMask, UP); + PORTEVENT_SETMASKBIT(nimEventMask, DOWN); + PORTEVENT_SETMASKBIT(nimEventMask, PROBE_SETUP); + PORTEVENT_SETMASKBIT(nimEventMask, PROBE_TEARDOWN); + PORTEVENT_SETMASKBIT(nimEventMask, AUTHMGR_ACQUIRE); + nimRegisterIntfEvents( MAB_COMPONENT_ID, nimEventMask); + + (void) osapiTaskInitDone ( MAB_DB_TASK_SYNC); + + break; + + default: + break; + } + + endTime = osapiTimeMillisecondsGet(); + nimStartupEventDone( MAB_COMPONENT_ID); + + return SUCCESS; +} + +/********************************************************************* + * @purpose Process Link state changes + * + * @param intIfNum @b{(input)) internal interface number + * @param intIfEvent @b{(input)) interface event + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments none + * + * @end + *********************************************************************/ +RC_t mabIhProcessIntfChange(uint32 intIfNum, uint32 intfEvent, NIM_CORRELATOR_t correlator) +{ + uint32 linkState, adminState; + RC_t rc = SUCCESS; + uint32 currAcquired, prevAcquired; + NIM_EVENT_COMPLETE_INFO_t status; + mabPortCfg_t *pCfg; + uint32 lIntIfNum; + mabLogicalPortInfo_t *logicalPortInfo; + uchar8 ifName[ NIM_IF_ALIAS_SIZE + 1]; + + status.intIfNum = intIfNum; + status.component = MAB_COMPONENT_ID; + status.event = intfEvent; + status.correlator = correlator; + nimGetIntfName(intIfNum, ALIASNAME, ifName); + + if (!(MAB_IS_READY)) + { + LOGF( LOG_SEVERITY_INFO, + "Received an interface change callback while MAB not ready to receive it."); + MAB_EVENT_TRACE("%s:%d Nim Event %d received for %s when mab is not ready \n", + __FUNCTION__,__LINE__,intfEvent,ifName); + rc = FAILURE; + status.response.rc = rc; + nimEventStatusCallback(status); + return rc; + } + + MAB_EVENT_TRACE("%s:%d Nim Event %d received for %s \n", + __FUNCTION__,__LINE__,intfEvent,ifName); + + if (mabIsValidIntf(intIfNum) != TRUE) + { + rc = SUCCESS; + status.response.rc = rc; + nimEventStatusCallback(status); + return rc; + } + + switch (intfEvent) + { + case UP: + case PORT_ENABLE: + mabBlock->mabPortInfo[intIfNum].portEnabled = FALSE; + if (mabIntfIsConfigurable(intIfNum, &pCfg) == TRUE) + { + if (nimGetIntfLinkState(intIfNum, &linkState) == SUCCESS) + { + if ( (nimGetIntfAdminState(intIfNum, &adminState) == SUCCESS) && + (adminState == ENABLE) && + (nimGetIntfLinkState(intIfNum, &linkState) == SUCCESS) && + (linkState == UP) ) + { + mabBlock->mabPortInfo[intIfNum].portEnabled = TRUE; + } + else + { + mabBlock->mabPortInfo[intIfNum].portEnabled = FALSE; + } + } + + if (mabBlock->mabPortInfo[intIfNum].portEnabled == TRUE) + { + { + /* Cleanup any existing clients on the port before reset */ + mabPortInfoCleanup(intIfNum); + (void) mabPortReset(intIfNum); + (void) mabCtlApplyPortConfigData(intIfNum); + } + } + } + break; + + case PROBE_TEARDOWN: + /* update aquired list */ + COMPONENT_ACQ_CLRMASKBIT(mabBlock->mabPortInfo[intIfNum].acquiredList, PORT_MIRROR_COMPONENT_ID); + + + /* check if currently acquired */ + COMPONENT_ACQ_NONZEROMASK(mabBlock->mabPortInfo[intIfNum].acquiredList, currAcquired); + + /* If the interface is not currently acquired by some component, cause + * the acquisition to be reflected in the state of the spanning tree + */ + if (currAcquired == FALSE) + { + if (nimGetIntfLinkState(intIfNum, &linkState) == SUCCESS) + { + if ( (nimGetIntfAdminState(intIfNum, &adminState) == SUCCESS) && + (adminState == ENABLE) && + (nimGetIntfLinkState(intIfNum, &linkState) == SUCCESS) && + (linkState == UP) ) + { + mabBlock->mabPortInfo[intIfNum].portEnabled = TRUE; + /* Cleanup any existing clients on the port before reset */ + mabPortInfoCleanup(intIfNum); + (void) mabPortReset(intIfNum); + (void) mabCtlApplyPortConfigData(intIfNum); + } + } + } + break; + + case DOWN: + case PORT_DISABLE: + + if (mabIntfIsConfigurable(intIfNum, &pCfg) == TRUE ) + { + lIntIfNum = MAB_LOGICAL_PORT_ITERATE; + while ((logicalPortInfo=mabLogicalPortInfoGetNextNode(intIfNum,&lIntIfNum))!= NULLPTR) + { + if (0 == logicalPortInfo->key.keyNum) + continue; + + if (mabBlock->mabPortInfo[intIfNum].portControlMode == AUTHMGR_PORT_AUTO) + { + mabPortInfoCleanup(intIfNum); + } + } + } + break; + + case PROBE_SETUP: + /* check if previously acquired */ + COMPONENT_ACQ_NONZEROMASK(mabBlock->mabPortInfo[intIfNum].acquiredList, prevAcquired); + COMPONENT_ACQ_SETMASKBIT(mabBlock->mabPortInfo[intIfNum].acquiredList, PORT_MIRROR_COMPONENT_ID); + + /* If the interface was not previously acquired by some component, cause + * the acquisition to be reflected in the state of the spanning tree + */ + if (prevAcquired == FALSE) + { + if (mabBlock->mabPortInfo[intIfNum].portControlMode != AUTHMGR_PORT_FORCE_AUTHORIZED) + { + /* reset all the clients associated with the port if port control mode is Macbased */ + if (mabBlock->mabPortInfo[intIfNum].portControlMode == AUTHMGR_PORT_AUTO) + { + /* remove clients from any associated vlans*/ + mabPortInfoCleanup(intIfNum); + /* reset all the clients associated with the port */ + (void) mabPortReset(intIfNum); + (void) mabCtlApplyPortConfigData(intIfNum); + } + } + } + break; + + case CREATE: + rc = mabIntfCreate(intIfNum); + break; + + case ATTACH: + if (mabIntfIsConfigurable(intIfNum, &pCfg) == TRUE) + { + (void) mabPortReset(intIfNum); + } + else + { + rc = FAILURE; + } + break; + + case DETACH: + rc = mabIntfDetach(intIfNum); + break; + + case DELETE: + rc = mabIntfDelete(intIfNum); + break; + + case AUTHMGR_ACQUIRE: + rc = SUCCESS; + break; + + default: + break; + } + + status.response.rc = rc; + nimEventStatusCallback(status); + + return rc; +} + +/********************************************************************* + * @purpose bring up the individual interface + * + * @param warmRestart BOOL true if restart type is warm + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments Handle the events ATTACH, UP, Acquire etc + * + * @end + *********************************************************************/ +RC_t mabIntfStart(uint32 intIfNum, BOOL warmRestart) +{ + mabPortCfg_t *pCfg; + RC_t rc = FAILURE; + uint32 portLinkState; + COMPONENT_IDS_t acqCompId = FIRST_COMPONENT_ID; + uint32 adminState, count = 0; + BOOL probePort, restore = FALSE, skipFlag = FALSE; + BOOL needCleanup = TRUE; + + do + { + if (mabIntfIsConfigurable(intIfNum, &pCfg) != TRUE) + { + return rc; + } + + + /* Link state */ + rc = nimGetIntfLinkState(intIfNum, &portLinkState); + if (rc != SUCCESS) + { + break; + } + rc = nimGetIntfAdminState(intIfNum, &adminState); + if (rc != SUCCESS) + { + break; + } + + if (( TRUE != warmRestart) || + (0 == count)) + { + (void) mabPortReset (intIfNum); + rc = mabCtlApplyPortConfigData (intIfNum); + } + else + { + (void) mabPortReset (intIfNum); + + mabPortInfoInitialize (intIfNum, TRUE); + skipFlag = TRUE; + } + + + if (probePort) + { + acqCompId = PORT_MIRROR_COMPONENT_ID; + } + + if (acqCompId != FIRST_COMPONENT_ID) + { + COMPONENT_ACQ_SETMASKBIT(mabBlock->mabPortInfo[intIfNum].acquiredList, acqCompId); + } + else + { + if (portLinkState == UP) + { + if ((restore) && (warmRestart == TRUE) && (skipFlag == TRUE) && + ((mabBlock->mabPortInfo[intIfNum].portControlMode == AUTHMGR_PORT_AUTO))) + { + count = 0; + if (0 != count) + { + needCleanup = FALSE; + } + } + } /* end if link state is up*/ + }/* end intf not acquired*/ + } + while ( FALSE); + /* Acquire /Release*/ + return rc; + +} + +/********************************************************************* + * @purpose Process the activate startup callback from NIM + * + * @param + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments none + * + * @end + *********************************************************************/ +RC_t mabIntfActivateStartup() +{ + RC_t rc; + uint32 intIfNum = 0; + + rc = nimFirstValidIntfNumber(&intIfNum); + + while (rc == SUCCESS) + { + if (mabIsValidIntf(intIfNum) == TRUE) + { + mabIntfStart(intIfNum, mabIsRestartTypeWarm()); + } + rc = nimNextValidIntfNumber(intIfNum, &intIfNum); + } + + mabBlock->mabSwitchoverInProgress = FALSE; + mabWarmRestartTypeSet(FALSE); + + return SUCCESS; +} + +/********************************************************************* + * @purpose Obtain a pointer to the specified interface configuration data + * for this interface + * + * @param intIfNum @b{(input)} Internal Interface Number + * @param **pCfg @b{(output)} Ptr to mab port config structure + * or NULL if not needed + * + * @returns TRUE + * @returns FALSE + * + * + * @comments Facilitates pre-configuration, as it checks if the NIM + * interface exists and whether the component is in a state to + * be configured (regardless of whether the component is enabled + * or not). + * + * @comments The caller can set the pCfg parm to NULL if it does not + * want the value output from this function. + * + * @end + *********************************************************************/ + BOOL mabIntfIsConfigurable(uint32 intIfNum, mabPortCfg_t **pCfg) +{ + nimConfigID_t configId; + uchar8 ifName[ NIM_IF_ALIAS_SIZE + 1]; + nimGetIntfName(intIfNum, ALIASNAME, ifName); + + if (!(MAB_IS_READY)) + return FALSE; + + /* Check boundary conditions */ + if (intIfNum <= 0 || intIfNum >= MAB_INTF_MAX_COUNT) + return FALSE; + + + /* verify that the configId in the config data table entry matches the configId that NIM maps to + ** the intIfNum we are considering + */ + if (nimConfigIdGet(intIfNum, &configId) == SUCCESS) + { + if (NIM_CONFIG_ID_IS_EQUAL(&configId, &(mabBlock->mabCfg->mabPortCfg[intIfNum].configId)) == TRUE) + { + *pCfg = &mabBlock->mabCfg->mabPortCfg[intIfNum]; + return TRUE; + } + } + + /* if we get here, either we have a table management error between mabCfg and mabMapTbl or + ** there is synchronization issue between NIM and components w.r.t. interface creation/deletion + */ + LOGF( LOG_SEVERITY_INFO, + "Error accessing MAB config data for interface %s in MAB interface configuration.\n", ifName); + return FALSE; +} + +/********************************************************************* + * + * @purpose To process the Callback for CREATE + * + * @param uint32 intIfNum internal interface number + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments none + * + * @end + * + *********************************************************************/ +RC_t mabIntfCreate(uint32 intIfNum) +{ + nimConfigID_t configId; + mabPortCfg_t *pCfg; + + if (mabIsValidIntf(intIfNum) != TRUE) + return FAILURE; + + if (nimConfigIdGet(intIfNum, &configId) != SUCCESS) + return FAILURE; + + pCfg = &mabBlock->mabCfg->mabPortCfg[intIfNum]; + + if (!(NIM_CONFIG_ID_IS_EQUAL(&configId, &pCfg->configId))) + { + NIM_CONFIG_ID_COPY(&pCfg->configId, &configId); + /* If an interface configuration entry is not already assigned to the interface, assign one */ + /* Update the configuration structure with the config id */ + mabBuildDefaultIntfConfigData(&configId, pCfg); + } + + (void)mabCtlPortStatsClear(intIfNum); + + return SUCCESS; +} + +/********************************************************************* + * + * @purpose To process the Callback for DETACH + * + * @param uint32 intIfNum internal interface number + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments none + * + * @end + * + *********************************************************************/ +RC_t mabIntfDetach(uint32 intIfNum) +{ + mabPortCfg_t *pCfg; + + if (mabIntfIsConfigurable(intIfNum, &pCfg) == TRUE) + { + mabPortInfoCleanup(intIfNum); + (void)mabCtlApplyPortConfigData(intIfNum); + } + + return SUCCESS; +} + +/********************************************************************* + * + * @purpose To process the Callback for DELETE + * + * @param uint32 intIfNum internal interface number + * + * @returns SUCCESS + * @returns FAILURE + * + * @comments none + * + * @end + * + *********************************************************************/ +RC_t mabIntfDelete(uint32 intIfNum) +{ + mabPortCfg_t *pCfg; + + if (mabIntfIsConfigurable(intIfNum, &pCfg) == TRUE) + { + mabPortInfoCleanup(intIfNum); + + memset((void *)&pCfg->configId, 0, sizeof(nimConfigID_t)); + memset((void *)&mabBlock->mabMapTbl[intIfNum], 0, sizeof(uint32)); + memset((void *)&mabBlock->mabPortInfo[intIfNum], 0, sizeof(mabPortInfo_t)); + memset((void *)&mabBlock->mabPortStats[intIfNum], 0, sizeof(mabPortStats_t)); + } + + return SUCCESS; +} diff --git a/src/sonic-pac/mab/mapping/mab_init.c b/src/sonic-pac/mab/mapping/mab_init.c new file mode 100755 index 000000000000..5f881387e83d --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_init.c @@ -0,0 +1,254 @@ +/* + * Copyright 2024 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 "mab_include.h" +#include "mab_debug.h" +#include "mab_struct.h" +#include "mab_radius.h" +#include "osapi_sem.h" + +/*dummy declaration to resolve linking errors */ +#define platAuthMgrMaxUsersGet() (512) +static uint32 platIntfMaxCountGet (void) +{ + return MAX_INTERFACE_COUNT; +} + +mabBlock_t *mabBlock = NULLPTR; + + BOOL mabIsRestartTypeWarm() +{ + return mabBlock->warmRestart; +} + +void mabWarmRestartTypeSet( BOOL warmType) +{ + mabBlock->warmRestart = warmType; +} + +/********************************************************************* +* +* @purpose System Initialization for mab +* +* @param none +* +* @returns SUCCESS, if success +* @returns FAILURE, if other failure +* +* @comments none +* +* @end +*********************************************************************/ +RC_t mabInit(void) +{ + mabBlock = osapiMalloc( MAB_COMPONENT_ID, sizeof(mabBlock_t)); + + if ( NULLPTR == mabBlock) + { + return FAILURE; + } + + memset(mabBlock, 0, sizeof(mabBlock_t)); + /*semaphore creation for task protection over the common data*/ + mabBlock->mabTaskSyncSema = osapiSemaCCreate( OSAPI_SEM_Q_FIFO, OSAPI_SEM_EMPTY); + if (mabBlock->mabTaskSyncSema == NULL) + { + LOGF( LOG_SEVERITY_NOTICE, + "Unable to create mab task semaphore"); + return FAILURE; + } + + mabBlock->mabRadiusSrvrTaskSyncSema = osapiSemaCCreate( OSAPI_SEM_Q_FIFO, OSAPI_SEM_EMPTY); + if (mabBlock->mabRadiusSrvrTaskSyncSema == NULL) + { + LOGF( LOG_SEVERITY_NOTICE, + "Unable to create mab radius server task semaphore"); + return FAILURE; + } + + mabBlock->mabQueue = (void *)osapiMsgQueueCreate("mabQueue", MAB_MSG_COUNT, (uint32)sizeof(mabMsg_t)); + if (mabBlock->mabQueue == NULLPTR) + { + LOGF( LOG_SEVERITY_INFO, + "mabInit: msgQueue creation error.\n"); + return FAILURE; + } + + if (mabStartTasks() != SUCCESS) + { + return FAILURE; + } + + return SUCCESS; +} + +/********************************************************************* +* +* @purpose System Init Undo for mab +* +* @param none +* +* @comments none +* +* @end +*********************************************************************/ +void mabInitUndo() +{ + if (mabBlock->mabQueue != NULLPTR) + osapiMsgQueueDelete(mabBlock->mabQueue); + + (void)osapiRWLockDelete(mabBlock->mabRWLock); + + if ( NULL != mabBlock->mabTaskSyncSema) + { + (void)osapiSemaDelete(mabBlock->mabTaskSyncSema); + } + + if ( NULL != mabBlock->mabRadiusSrvrTaskSyncSema) + { + (void)osapiSemaDelete(mabBlock->mabRadiusSrvrTaskSyncSema); + } + + if (mabBlock->mabTaskId != 0) + osapiTaskDelete(mabBlock->mabTaskId); + + if ( NULLPTR != mabBlock) + { + osapiFree(MAB_COMPONENT_ID, mabBlock); + } +} + +/********************************************************************* +* @purpose This function performs the Phase 1 initialization. +* +* @param none +* +* @returns SUCCESS - There were no errors. +* +* @returns ERROR - There were errors. +* +* @comments none +* +* @end +*********************************************************************/ +RC_t mabInitPhase1Process(void) +{ + RC_t mabRC,rc; + uint32 mabMaxNodes; + + mabRC = SUCCESS; + + mabBlock->mabCfg = osapiMalloc( MAB_COMPONENT_ID, sizeof(mabCfg_t)); + mabBlock->mabPortInfo = osapiMalloc( MAB_COMPONENT_ID, sizeof(mabPortInfo_t) * MAB_INTF_MAX_COUNT); + + rc = mabLogicalPortInfoDBInit(platAuthMgrMaxUsersGet()); + + mabBlock->mabPortStats = osapiMalloc( MAB_COMPONENT_ID, sizeof(mabPortStats_t) * platIntfMaxCountGet()); + mabBlock->mabMapTbl = osapiMalloc( MAB_COMPONENT_ID, sizeof(uint32) * platIntfMaxCountGet()); + + /* initialize Mac address database*/ + rc = mabMacAddrInfoDBInit(platAuthMgrMaxUsersGet()); + + mabMaxNodes = ((2*platIntfMaxCountGet()) + platAuthMgrMaxUsersGet() +1); + + /* Allocate buffer pool for App Timer */ + if (bufferPoolInit( MAB_COMPONENT_ID, 2 * mabMaxNodes, APP_TMR_NODE_SIZE, + "mab Timer Bufs", &mabBlock->mabAppTimerBufferPoolId) != SUCCESS) + { + mabRC = ERROR; + return mabRC; + } + + if ((mabBlock->mabCfg == NULLPTR) || + (mabBlock->mabPortInfo == NULLPTR) || + (rc == FAILURE) || + (mabBlock->mabPortStats == NULLPTR) || + (mabBlock->mabMapTbl == NULLPTR)) + { + mabRC = ERROR; + return mabRC; + } + + /* Zero bitmasks to indicate no interfaces are enabled */ + memset((void *)mabBlock->mabCfg, 0, sizeof(mabCfg_t)); + memset((void *)mabBlock->mabPortInfo, 0, sizeof(mabPortInfo_t) * MAB_INTF_MAX_COUNT); + memset((void *)mabBlock->mabPortStats, 0, sizeof(mabPortStats_t) * platIntfMaxCountGet()); + memset((void *)mabBlock->mabMapTbl, 0, sizeof(uint32) * platIntfMaxCountGet()); + + return mabRC; +} + +/********************************************************************* +* @purpose This function performs the Phase 2 initialization. +* +* @param none +* +* @returns SUCCESS - There were no errors. +* +* @returns ERROR - There were errors. +* +* @comments none +* +* @end +*********************************************************************/ +RC_t mabInitPhase2Process(void) +{ + RC_t mabRC = SUCCESS; + + if (nimRegisterIntfChange( MAB_COMPONENT_ID, mabIntfChangeCallback, + mabIntfStartupCallback, NIM_STARTUP_PRIO_MAB) != SUCCESS) + { + LOGF( LOG_SEVERITY_INFO, + "mab: Unable to register with NIM\n"); + mabRC = ERROR; + return mabRC; + } + + return mabRC; +} + +/********************************************************************* +* @purpose This function performs the Phase 3 initialization. +* +* @param none +* +* @returns SUCCESS - There were no errors. +* +* @returns ERROR - There were errors. +* +* @comments none +* +* @end +*********************************************************************/ +RC_t mabInitPhase3Process( BOOL warmRestart) +{ + RC_t mabRC; + mabRC = SUCCESS; + + if (warmRestart == TRUE) + { + mabBlock->mabSwitchoverInProgress = TRUE; + } + + mabBuildDefaultConfigData(); + + if (mabCtlApplyConfigData() != SUCCESS) + { + mabRC = ERROR; + } + + return mabRC; +} diff --git a/src/sonic-pac/mab/mapping/mab_socket.c b/src/sonic-pac/mab/mapping/mab_socket.c new file mode 100644 index 000000000000..957c45e0d685 --- /dev/null +++ b/src/sonic-pac/mab/mapping/mab_socket.c @@ -0,0 +1,462 @@ +/* + * Copyright 2024 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 +#include +#include +#include +#include +#include "mab_api.h" +#include "mab_include.h" +#include "mab_socket.h" +#include "fpSonicUtils.h" + +#define MAX_CLIENTS 1024 +#define MAB_NO_SOCKET -1 +#define MAB_TID_INIT -1 +#define MAB_SERVER_IPV4_ADDR "127.0.0.1" +#define MAB_SERVER_LISTEN_PORT 3734 +#define MAB_MAX_SEND_SIZE 1024 + +typedef struct connection_list_e +{ + int socket; + pthread_t tid; +}connection_list_t; + +static connection_list_t connection_list[MAX_CLIENTS] = {}; + +#define MAB_COPY(_a) static int _a##_##COPY(void *in, void *out) +#define MAB_ENTER(_a, _b, _c, _rc) _rc = _a##_##COPY(_b, _c) + +int mab_cmd_ping(unsigned int intf, char *resp) +{ + unsigned int status = 0; + + mabPortOperMABEnabledGet(intf, &status); + + if (status) + { + strncpy(resp, "PONG", strlen("PONG")+1); + } + else + { + strncpy(resp, "NO RESP", strlen("NO RESP")+1); + } + + return 0; +} + +int mab_cmd_event_notify(unsigned int intf, unsigned int event , unsigned char *mac, char *resp) +{ + int rc = 0; + enetMacAddr_t mac_addr; + + memcpy(mac_addr.addr, mac, 6); + + rc = mabClientEventUpdate(intf, event, &mac_addr); + + if (!rc) + { + strncpy(resp, "OK", strlen("OK")+1); + } + else + { + strncpy(resp, "FAIL", strlen("FAIL")+1); + } + + return 0; +} + +MAB_COPY(INTERFACE) +{ + + char *intfStr = (char *)in; + unsigned int intf = 0; + + fpGetIntIfNumFromHostIfName(intfStr, &intf); + (*(unsigned int *)out) = intf; + + return 0; +} + +MAB_COPY(CMD) +{ + mab_pac_cmd_t *req = (mab_pac_cmd_t *)in; + char *resp = (char *)out; + unsigned int intf = 0; + int rc = 0; + + /* convert char intf to intf number */ + MAB_ENTER(INTERFACE, (void *)req->intf, (void *)&intf, rc); + + printf("MAB ENTER INTERFACE !! rc %d \n", rc); + + if (0 != rc) + return -1; + + if (0 == strncmp("PING", req->cmd, strlen("PING"))) + { + rc = mab_cmd_ping(intf, resp); + } + else if (0 == strncmp("event-notify", req->cmd, strlen("event-notify")+1)) + { + rc = mab_cmd_event_notify(intf, req->notif_event, req->mac_addr, resp); + } + else + { + strncpy(resp, "unknown cmd", strlen("unknown cmd")+1); + } + + return 0; +} + +/* Start listening socket listen_sock. */ +int start_listen_socket(int *listen_sock) +{ + int reuse = 1; + struct sockaddr_in my_addr; + + /* Obtain a file descriptor for our "listening" socket. */ + *listen_sock = socket(AF_INET, SOCK_STREAM, 0); + if (*listen_sock < 0) + { + perror("socket"); + return -1; + } + + if (setsockopt(*listen_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != 0) { + perror("setsockopt"); + return -1; + } + + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = inet_addr(MAB_SERVER_IPV4_ADDR); + my_addr.sin_port = htons(MAB_SERVER_LISTEN_PORT); + + if (bind(*listen_sock, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0) { + perror("bind"); + return -1; + } + + /* start accept client connections */ + if (listen(*listen_sock, 144) != 0) { + perror("listen"); + return -1; + } + printf("Accepting connections on port %d.\n", (int)MAB_SERVER_LISTEN_PORT); + + return 0; +} + + +void connection_close(int conn_socket) +{ + int i; + + for (i = 0; i < MAX_CLIENTS; ++i) { + if (connection_list[i].socket == conn_socket) { + close(connection_list[i].socket); + connection_list[i].socket = MAB_NO_SOCKET; + } + } +} + + +/* Receive message from peer and handle it with message_handler(). */ +int read_from_connection(int socket, char *buf, unsigned int buf_len, + unsigned int *bytes_read, bool *more_data) +{ + size_t len_to_receive; + ssize_t received_count = 0; + size_t received_total = 0; + + char *buf_ptr = buf; + + MAB_EVENT_TRACE( + "Entering read_from_connection fd %d buf_len %d\n", socket, buf_len); + + + do { + if (received_total >= buf_len) + { + /* still more to copy */ + *more_data = true; + *bytes_read = received_total; + MAB_EVENT_TRACE( + "fd: %d There is more data , Read %zd bytes till now", + socket, received_count); + + return 0; + } + + /* Count bytes to receive.*/ + len_to_receive = buf_len; + if (len_to_receive > MAB_MAX_SEND_SIZE) + len_to_receive = MAB_MAX_SEND_SIZE; + + MAB_EVENT_TRACE( + "fd: %d Let's try to recv() %zd bytes... ", socket, len_to_receive); + + received_count = recv(socket, buf_ptr, len_to_receive, NULL); + + if (received_count < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + MAB_EVENT_TRACE( + "fd %d peer is not ready right now, try again later.\n", socket); + continue; + } + else { + perror("recv() from peer error"); + *more_data = false; + return -1; + } + } + + /* If recv() returns 0, it means that peer gracefully shutdown. Shutdown client.*/ + else if (received_count == 0) { + MAB_EVENT_TRACE( + "fd %d recv() 0 bytes. Peer gracefully shutdown.\n", socket); + *more_data = false; + break; + } + else if (received_count > 0) { + received_total += received_count; + MAB_EVENT_TRACE( + "fd %d recv() %zd bytes\n", socket, received_count); + + buf_ptr += received_count; + len_to_receive -= received_count; + *more_data = false; + break; + } + + } while (received_count > 0); + + *bytes_read = received_total; + + MAB_EVENT_TRACE( + "fd %d Total recv()'ed %zu bytes.\n", socket, received_total); + return 0; +} + +void close_connection(int conn_socket) +{ + close(conn_socket); +} + +void *new_connection_handle(void *arg) +{ + int new_socket = *((int *)arg); + char recv_buff[2048] = {0}; + char resp_buff[256] = {0}; + char *buf = &recv_buff[0]; + unsigned int bytes_received; + bool more_data = true; + int rem_len = sizeof(recv_buff); + int total_read = 0; + int rc = -1; + + int i; + char *ptr = &recv_buff[0]; + + while(more_data) + { + more_data = false; + if (rem_len <= 0) + { + MAB_EVENT_TRACE( + "fd: %d More data to read, but not sufficient buffer !!\n", new_socket); + break; + } + bytes_received = 0; + if (0 != read_from_connection(new_socket, buf, rem_len, &bytes_received, &more_data)) + { + break; + } + buf = recv_buff + bytes_received; + total_read += bytes_received; + rem_len = sizeof(recv_buff) - total_read; + } + + printf("buffer: "); + for (i =0; i<10; i++) + { + printf("0x%x ", ptr[i]); + } + printf("\n"); + + MAB_EVENT_TRACE( + "fd :%d start processing the cmd and send resp!!\n", new_socket); + + MAB_ENTER(CMD, (void *)recv_buff, (void *)resp_buff, rc); + + if (strlen(resp_buff)) + { + /* send the response */ + rc = send(new_socket, resp_buff, sizeof(resp_buff), 0); + + MAB_EVENT_TRACE( + "fd :%d Successfully sent data (len %lu bytes): %s\n", + new_socket, sizeof(resp_buff), resp_buff); + } + + free (arg); + close_connection(new_socket); + pthread_exit(NULL); +} + + +int new_connection_open(int new_client_sock) +{ + int *new_sock; + int ret = 0; + pthread_attr_t tattr; + static int cl_count; + + + if ((ret = pthread_attr_init(&tattr)) !=0) + { + MAB_EVENT_TRACE( + "Failed to create thread - pthread_attr_init failed with %d\n", ret); + close(new_client_sock); + return -1; + } + + if ((ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED)) !=0) + { + MAB_EVENT_TRACE( + "Failed to create thread - pthread_attr_setdetachstate failed with %d\n", ret); + close(new_client_sock); + pthread_attr_destroy(&tattr); + return -1; + } + + new_sock = malloc(sizeof(*new_sock)); + *new_sock = new_client_sock; + + connection_list[cl_count].socket = new_client_sock; + connection_list[cl_count].tid = MAB_TID_INIT; + + if ((ret = pthread_create(&connection_list[cl_count].tid, &tattr, + new_connection_handle, (void*)new_sock)) !=0) + { + MAB_EVENT_TRACE( + "Failed to create thread\n"); + free(new_sock); + connection_close(new_client_sock); + pthread_attr_destroy(&tattr); + return -1; + } + cl_count = (cl_count+1)%MAX_CLIENTS; + pthread_attr_destroy(&tattr); + return 0; +} + + +int mab_socket_server_handle(int *listen_sock) +{ + int i; + int new_client_sock = -1; + struct sockaddr_in client_addr; + socklen_t client_len = sizeof(client_addr); + char client_ipv4_str[INET_ADDRSTRLEN]; + + if (start_listen_socket(listen_sock) != 0) { + return -1; + } + + for (i = 0; i < MAX_CLIENTS; ++i) + { + connection_list[i].socket = MAB_NO_SOCKET; + connection_list[i].tid = MAB_TID_INIT; + } + + while (1) + { + new_client_sock = -1; + printf("calling accept.\n"); + + memset(&client_addr, 0, sizeof(client_addr)); + + new_client_sock = accept(*listen_sock, (struct sockaddr *)&client_addr, &client_len); + if (new_client_sock < 0) { + perror("accept()"); + continue; + } + + inet_ntop(AF_INET, &client_addr.sin_addr, client_ipv4_str, INET_ADDRSTRLEN); + + MAB_EVENT_TRACE( + "Incoming connection from client fd %d [%s:%u] ", + new_client_sock, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + + new_connection_open(new_client_sock); + } + return 0; +} + +int mab_radius_init_recv_socket(int *sock) +{ + struct sockaddr_in s_addr; + *sock = -1; + + /* create the mab server socket */ + *sock = socket(AF_INET, SOCK_DGRAM, 0); + if (*sock < 0) { + MAB_EVENT_TRACE( + "socket[AF_INET,SOCK_DGRAM]: %s", + strerror(errno)); + return -1; + } + + memset(&s_addr, 0, sizeof(s_addr)); + s_addr.sin_family = AF_INET; + s_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + s_addr.sin_port = htons(9395); + + if (bind(*sock, (const struct sockaddr *)&s_addr, + sizeof(s_addr)) < 0 ) + { + perror("bind failed"); + return -1; + } + return 0; +} + + +int mab_radius_init_send_socket(int *sock) +{ + *sock = -1; + + /* create the mab send socket */ + *sock = socket(AF_INET, SOCK_DGRAM, 0); + if (*sock < 0) { + MAB_EVENT_TRACE( + "socket[AF_INET,SOCK_DGRAM]: %s", + strerror(errno)); + return -1; + } + return 0; +} + +