Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d5b8606
Description: Monitor DHCP packet in packet handler and
rhegde114 Dec 10, 2025
41ffb24
Description: Monitor DHCP packet in packet handler and
rhegde114 Dec 10, 2025
71a7394
Description: Monitor DHCP packet in packet handler and
rhegde114 Dec 10, 2025
7071f67
Description: Monitor DHCP packet in packet handler and
rhegde114 Dec 10, 2025
626243e
Description: Monitor DHCP packet in packet handler and
rhegde114 Dec 10, 2025
dcc155d
Merge branch 'rdkcentral:develop' into snooper_test
rhegde114 Dec 30, 2025
d66ad42
Description: Monitor DHCP packet in packet handler and
rhegde114 Jan 6, 2026
4effa6c
Description: Monitor DHCP packet in packet handler and
rhegde114 Jan 6, 2026
be7401e
Revert "Description: Monitor DHCP packet in packet handler and"
rhegde114 Jan 20, 2026
0d4fbed
Description: Monitor DHCP packet in packet handler and
rhegde114 Jan 20, 2026
f63c619
Description: Monitor DHCP packet in packet handler and
rhegde114 Jan 20, 2026
614a658
Description: Monitor DHCP packet in packet handler and
rhegde114 Jan 20, 2026
dd84407
Merge branch 'rdkcentral:develop' into snooper_test
rhegde114 Jan 21, 2026
c546e58
Merge branch 'rdkcentral:develop' into snooper_test
rhegde114 Feb 13, 2026
3133ed6
Description: Monitor DHCP packet in packet handler and
rhegde114 Feb 13, 2026
8a3b853
Merge branch 'rdkcentral:develop' into snooper_test
rhegde114 Feb 24, 2026
39bd424
Description: Monitor DHCP packet in packet handler and
rhegde114 Feb 25, 2026
03dc052
Description: Monitor DHCP packet in packet handler and
rhegde114 Feb 25, 2026
c657715
Description: Monitor DHCP packet in packet handler and
rhegde114 Feb 25, 2026
6042489
Description: Monitor DHCP packet in packet handler and
rhegde114 Feb 25, 2026
2965559
Merge branch 'rdkcentral:develop' into snooper_test
rhegde114 Mar 5, 2026
cac2e0b
Merge branch 'rdkcentral:develop' into snooper_test
rhegde114 Mar 27, 2026
f2c3fbb
Merge branch 'rdkcentral:develop' into snooper_test
rhegde114 Apr 2, 2026
53225bd
Description: Monitor DHCP packet in packet handler and
rhegde114 Apr 2, 2026
d306f0a
Description: Monitor DHCP packet in packet handler and
rhegde114 Apr 2, 2026
4d49f40
Description: Monitor DHCP packet in packet handler and
rhegde114 Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/hotspotfd/cosa_hotspot_dml.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ BOOL HotspotConnectedDevice_SetParamStringValue(ANSC_HANDLE hInsContext, char* P
{
CcspTraceInfo(("Added case, Client with MAC:%s will be added\n", l_cMacAddr));
t2_event_d("WIFI_INFO_Hotspot_client_connected", 1);
updateRssiForClient(l_cMacAddr, l_iRssi);
updateRssiForClient(l_cMacAddr, l_iRssi, l_iSsidIndex);
}
else
{
Expand Down
232 changes: 220 additions & 12 deletions source/hotspotfd/dhcpsnooper.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
#include <telemetry_busmessage_sender.h>
#include "safec_lib_common.h"
#include "libHotspot.h"

#include <rbus.h>

#define mylist_safe(p, q, h) \
if ((h)->n == NULL ) { \
Expand Down Expand Up @@ -133,6 +133,8 @@ static char g_cHostnameForQueue[kSnoop_MaxCircuitIDs][kSnooper_MaxHostNameLen];
static char g_cInformIpForQueue[kSnoop_MaxCircuitIDs][INET_ADDRSTRLEN];
extern vlanSyncData_s gVlanSyncData[];
extern int gVlanSyncDataSize;
client_node_t *client_list = NULL;
extern rbusHandle_t disassoc_rbus_handle;

#if 0
static void snoop_setDhcpRelayAgentAddAgentOptions(int aao)
Expand All @@ -155,6 +157,130 @@ static enum agent_relay_mode_t snoop_getDhcpRelayAgentMode( )
return agent_relay_mode;
}
#endif

int publish_to_onewifi(char *cmdStr)
{
rbusError_t rc = RBUS_ERROR_SUCCESS;
rbusValue_t value;
rbusObject_t data;
rbusEvent_t event;

msg_debug("Command string: %s - %s\n", cmdStr, __FUNCTION__);

if (cmdStr == NULL || strlen(cmdStr) == 0) {
msg_debug("mac address empty and not sending rbus event to onewifi: %d\n", __LINE__);
return 0;
}

// Initialize RBus value and object
rbusValue_Init(&value);
rbusValue_SetString(value, cmdStr);
rbusObject_Init(&data, NULL);
rbusObject_SetValue(data, "Device.X_COMCAST-COM_GRE.Hotspot.RejectAssociatedClient", value);

// Publish event directly to subscribers (OneWifi)
event.name = "Device.X_COMCAST-COM_GRE.Hotspot.RejectAssociatedClient";
event.data = data;
event.type = RBUS_EVENT_GENERAL;

rc = rbusEvent_Publish(disassoc_rbus_handle, &event);

// Clean up
rbusValue_Release(value);
rbusObject_Release(data);

if (rc != RBUS_ERROR_SUCCESS) {
msg_debug("Failed to publish RBus event: error code %d (line %d)\n", rc, __LINE__);
return 0;
}

msg_debug("Successfully published deauth event to OneWifi via RBus\n");
return 1;
}

dhcp_client_state_t* get_client_state(const char *mac)
{
if (mac == NULL || strlen(mac) == 0) {
msg_debug("get_client_state: Invalid MAC address input\n");
return NULL;
}

client_node_t *cur = client_list;
while (cur) {
if (strcmp(cur->mac, mac) == 0)
return &cur->state;
cur = cur->next;
}

// Not found, create new
client_node_t *new_node = (client_node_t *)calloc(1, sizeof(client_node_t));
if (!new_node) {
msg_debug("get_client_state: Memory allocation failed for MAC %s\n", mac);
return NULL;
}
strncpy(new_node->mac, mac, sizeof(new_node->mac) - 1);
msg_debug("new_node->mac: %s\n", new_node->mac);
new_node->mac[sizeof(new_node->mac) - 1] = '\0';
new_node->next = client_list;
client_list = new_node;
return &new_node->state;
}

// Remove client node from the linked list by MAC address
void remove_client_state(const char *mac)
{
if (!mac || !client_list)
return;
client_node_t *prev = NULL, *cur = client_list;
while (cur)
{
if (strcmp(cur->mac, mac) == 0)
{
if (prev)
{
prev->next = cur->next;
}
else
{
client_list = cur->next;
}
free(cur);
return;
}
prev = cur;
cur = cur->next;
}
}

static void constructCommand(char *macaddr, char *cmd)
{
snooper_priv_client_list * pNewClient;
struct mylist_head * pos, * q;
bool already_in_list = false;
char macaddr_with_index[64] = {0};
pthread_mutex_lock(&global_stats_mutex);
mylist_safe(pos, q, &gSnoop_ClientList.list)
{

pNewClient= mylist_entry(pos, snooper_priv_client_list, list);
if(!strcasecmp(pNewClient->client.remote_id, macaddr))
{
already_in_list = true;
break;
}
}
if(already_in_list)
{
msg_debug("Client:%s is present in list\n", macaddr);
snprintf(macaddr_with_index, sizeof(macaddr_with_index), "%s_%d", macaddr, pNewClient->client.vapIndex);
macaddr_with_index[sizeof(macaddr_with_index) - 1] = '\0';
}
strncpy(cmd, macaddr_with_index, sizeof(macaddr_with_index) - 1);
msg_debug("constructCommand :%s\n", cmd);
pthread_mutex_unlock(&global_stats_mutex);

}

#if defined (AMENITIES_NETWORK_ENABLED)
static BOOL isValidAmenityQueue(int queue_number, int *pIndex)
{
Expand Down Expand Up @@ -740,7 +866,7 @@ static void snoop_CheckClientIsPrivate(char *pRemote_id)
}

static void snoop_AddClientListEntry(char *pRemote_id, char *pCircuit_id,
char *pDhcp_status, char *pIpv4_addr, char *pHostname, int rssi)
char *pDhcp_status, char *pIpv4_addr, char *pHostname, int rssi,int vap_index)
{
errno_t rc = -1;
snooper_priv_client_list * pNewClient;
Expand Down Expand Up @@ -820,6 +946,7 @@ static void snoop_AddClientListEntry(char *pRemote_id, char *pCircuit_id,
}
}
pNewClient->client.rssi = rssi;
pNewClient->client.vapIndex = vap_index;
pNewClient->client.noOfTriesForOnlineCheck = 0;
mylist_add(&pNewClient->list, &gSnoop_ClientList.list);
gSnoopNumberOfClients++;
Expand Down Expand Up @@ -870,7 +997,8 @@ static void snoop_AddClientListEntry(char *pRemote_id, char *pCircuit_id,
}
else
{
pNewClient->client.rssi = rssi;
pNewClient->client.rssi = rssi;
pNewClient->client.vapIndex = vap_index;
}
}
mutex_cleanup:
Expand Down Expand Up @@ -1005,6 +1133,13 @@ static bool snoop_isValidIpAddress(char *ipAddress)
return (result != 0 && sa.sin_addr.s_addr != 0);
}

// Function to calculate the elapsed time in milliseconds
static long calculate_elapsed_time(struct timespec start) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return (now.tv_sec - start.tv_sec) * 1000 + (now.tv_nsec - start.tv_nsec) / 1000000;
}

static int snoop_packetHandler(struct nfq_q_handle * myQueue, struct nfgenmsg *msg,struct nfq_data *pkt, void *cbData)
{
UNREFERENCED_PARAMETER(msg);
Expand All @@ -1021,6 +1156,7 @@ static int snoop_packetHandler(struct nfq_q_handle * myQueue, struct nfgenmsg *m
struct iphdr *iph = NULL;
/* Coverity Fix CID: 74885 UnInit var */
char ipv4_addr[INET_ADDRSTRLEN] = {0};
char macaddr_with_index[64] = {0};

// The iptables queue number is passed when this handler is registered
// with nfq_create_queue
Expand Down Expand Up @@ -1082,6 +1218,36 @@ static int snoop_packetHandler(struct nfq_q_handle * myQueue, struct nfgenmsg *m
}
}

char mac_str[18];
snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x",
pktData[56], pktData[57], pktData[58], pktData[59], pktData[60], pktData[61]);
dhcp_client_state_t *state = get_client_state(mac_str);
if (!state)
{
msg_debug("Failed to create client state for MAC %s\n", mac_str);
}

// Check if the timer has exceeded 3 seconds
if (state != NULL && state->timer_running)
{
long elapsed_time = calculate_elapsed_time(state->dhcp_timer_start);
if (elapsed_time >= 3000)
{
if (!(state->dhcp_discover && state->dhcp_request && state->dhcp_offer && state->dhcp_ack))
{
constructCommand(mac_str, macaddr_with_index);
if (macaddr_with_index[0] != '\0' && publish_to_onewifi(macaddr_with_index))
{
msg_debug("DHCP ACK not received for client MAC.Publising RBus event Timer stopped. Time elapsed: %ld s - line %d\n",
(elapsed_time/1000), __LINE__);
}
}
state->timer_running = false;
state->dhcp_discover = state->dhcp_request = state->dhcp_offer = state->dhcp_ack = false; // Reset for next session
remove_client_state(mac_str);
state = NULL;
}
}
// If gSnoopEnable is not set then just send the packet out
if (((pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Request) || (pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Discover) ||
(pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Decline) || (pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Release) || (pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Inform))
Expand All @@ -1099,12 +1265,31 @@ static int snoop_packetHandler(struct nfq_q_handle * myQueue, struct nfgenmsg *m
}
else
#endif

if(state != NULL && pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Discover)
{
msg_debug("%s:%d> DHCP Discover\n", __FUNCTION__, __LINE__);
if (!state->timer_running) {
Comment thread
rhegde114 marked this conversation as resolved.
clock_gettime(CLOCK_MONOTONIC, &state->dhcp_timer_start);
state->timer_running = true;
state->ipv4_addr[0] = '\0';
state->dhcp_discover = true;
state->dhcp_request = false;
state->dhcp_offer = false;
state->dhcp_ack = false;
}
}
if(state !=NULL && pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Request)
{
msg_debug("%s:%d> DHCP Request\n", __FUNCTION__, __LINE__);
state->dhcp_request = true;
Comment thread
rhegde114 marked this conversation as resolved.
Comment thread
rhegde114 marked this conversation as resolved.
}
rc = strcpy_s(gCircuit_id, sizeof(gCircuit_id), gSnoopCircuitIDList[queue_number]);
if(rc != EOK)
{
ERR_CHK(rc);
return -1;
}
if(rc != EOK)
{
ERR_CHK(rc);
return -1;
}
msg_debug("gCircuit_id: %s\n", gCircuit_id);
sprintf(gRemote_id, "%02x:%02x:%02x:%02x:%02x:%02x",
pktData[56], pktData[57], pktData[58], pktData[59], pktData[60], pktData[61]);
Expand Down Expand Up @@ -1208,7 +1393,29 @@ static int snoop_packetHandler(struct nfq_q_handle * myQueue, struct nfgenmsg *m

if ( (pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Offer) ||
(pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_ACK))
{
{
if(state != NULL && pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_Offer)
{
msg_debug("%s:%d> DHCP Offer\n", __FUNCTION__, __LINE__);
state->dhcp_offer = true;
Comment thread
rhegde114 marked this conversation as resolved.
Comment thread
rhegde114 marked this conversation as resolved.
}
else if(state != NULL && pktData[kSnoop_DHCP_Option53_Offset] == kSnoop_DHCP_ACK)
{
msg_debug("%s:%d> DHCP ACK\n", __FUNCTION__, __LINE__);
memset(state->ipv4_addr, 0, sizeof(state->ipv4_addr));
Comment thread
rhegde114 marked this conversation as resolved.
Comment thread
rhegde114 marked this conversation as resolved.
inet_ntop(AF_INET, &(pktData[44]), state->ipv4_addr, INET_ADDRSTRLEN);
if (strcmp(state->ipv4_addr, "172.20.20.20") == 0) {
state->dhcp_ack = true;
}
}
if (state != NULL && state->timer_running && state->dhcp_discover && state->dhcp_request && state->dhcp_offer && state->dhcp_ack)
{
long elapsed_time = calculate_elapsed_time(state->dhcp_timer_start);
msg_debug("All DHCP states completed with ACK IP 172.20.20.20 in %ld ms. Timer stopped.\n", elapsed_time);
state->timer_running = false;
state->dhcp_discover = state->dhcp_request = state->dhcp_offer = state->dhcp_ack = false;
remove_client_state(mac_str);
}
msg_debug("%s:%d> DHCP Offer / DHCP Ack:%d received from server \n", __FUNCTION__, __LINE__, pktData[kSnoop_DHCP_Option53_Offset]);
new_data_len = snoop_removeRelayAgentOptions((struct dhcp_packet *)&pktData[kSnoop_DHCP_Options_Start], len, queue_number);

Expand Down Expand Up @@ -1335,7 +1542,7 @@ static int snoop_packetHandler(struct nfq_q_handle * myQueue, struct nfgenmsg *m
ERR_CHK(rc);
return -1;
}
snoop_AddClientListEntry(gRemote_id, gCircuit_id, "ACK", ipv4_addr, l_cHostName, 0);
snoop_AddClientListEntry(gRemote_id, gCircuit_id, "ACK", ipv4_addr, l_cHostName, 0,0);
Comment thread
bunnam988 marked this conversation as resolved.
snoop_CheckClientIsPrivate(gRemote_id);
}
snoop_log();
Expand All @@ -1350,7 +1557,7 @@ static int snoop_packetHandler(struct nfq_q_handle * myQueue, struct nfgenmsg *m
}
}

void updateRssiForClient(char* pRemote_id, int rssi)
void updateRssiForClient(char* pRemote_id, int rssi,int vap_index)
{
bool already_in_list = false;
struct mylist_head * pos, * q;
Expand All @@ -1363,14 +1570,15 @@ void updateRssiForClient(char* pRemote_id, int rssi)
if(!strcasecmp(pNewClient->client.remote_id, pRemote_id)) {
already_in_list = true;
pNewClient->client.rssi = rssi;
pNewClient->client.vapIndex = vap_index;
break;
}
}
pthread_mutex_unlock(&global_stats_mutex);
if (false == already_in_list)
{
msg_debug("Client :%s is not present Add to the clientlist\n", pRemote_id);
snoop_AddClientListEntry(pRemote_id, NULL, NULL, NULL, NULL, rssi);
snoop_AddClientListEntry(pRemote_id, NULL, NULL, NULL, NULL, rssi,vap_index);
}
else
{
Expand Down
Loading
Loading