Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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 src/sonic-pac/authmgr/common/auth_mgr_exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ typedef struct authmgrPortSessionStats_s
uint32 sessionPacketsGbRx;
uint32 sessionPacketsTx;
uint32 sessionPacketsGbTx;
uint32 sessionTime;
uint64 sessionTime; /* Y2038-safe: changed from uint32 */
uchar8 userName[AUTHMGR_USER_NAME_LEN];
char8 sessionId[AUTHMGR_SESSION_ID_LEN];
} authmgrPortSessionStats_t;
Expand Down
4 changes: 2 additions & 2 deletions src/sonic-pac/authmgr/protocol/include/auth_mgr_db.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,13 @@ typedef struct authmgrClientInfo_s
BOOL suppRestarting;

USER_MGR_AUTH_METHOD_t authMethod; /* Auth method for the user of this port */
uint32 sessionTime;
uint64 sessionTime; /* Y2038-safe: changed from uint32 */

uint32 clientTimeout;

uint32 sessionTimeout;
uint32 terminationAction;
uint32 lastAuthTime;
uint64 lastAuthTime; /* Y2038-safe: changed from uint32 */

AUTHMGR_PORT_MAB_AUTH_TYPE_t mabAuthType; /* Authentication type used by MAB. To be filled in only if isMABClient is TRUE */

Expand Down
4 changes: 2 additions & 2 deletions src/sonic-pac/pacoper/pacoper_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ typedef struct pac_authenticated_clients_oper_table_s
uint32 terminationAction;
authmgrVlanType_t vlanType; /* assigned vlan category */
uint32 vlanId;
uint32 sessionTime;
uint32 lastAuthTime;
uint64 sessionTime; /* Y2038-safe: changed from uint32 */
uint64 lastAuthTime; /* Y2038-safe: changed from uint32 */
USER_MGR_AUTH_METHOD_t backend_auth_method;

}pac_authenticated_clients_oper_table_t;
Expand Down
229 changes: 229 additions & 0 deletions src/sonic-pac/tests/test_y2038_timestamp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* Y2038 Timestamp Overflow Unit Tests for sonic-pac
*
* These tests verify that the Y2038 fix correctly handles 64-bit timestamps
* in the authentication manager data structures.
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>

/* Define uint64 type for testing (normally defined in datatypes.h) */
#ifndef uint64
typedef uint64_t uint64;
#endif

#ifndef uint32
typedef uint32_t uint32;
#endif

/* Test counters */
static int tests_passed = 0;
static int tests_failed = 0;

#define TEST_ASSERT(condition, message) \
do { \
if (condition) { \
tests_passed++; \
printf("[PASS] %s\n", message); \
} else { \
tests_failed++; \
printf("[FAIL] %s\n", message); \
} \
} while(0)

/* Test that uint64 type is correctly sized */
void test_uint64_type_size(void)
{
TEST_ASSERT(sizeof(uint64) == 8, "uint64 type is 8 bytes");
TEST_ASSERT(sizeof(uint64_t) == 8, "uint64_t type is 8 bytes");
}

/* Test that sessionTime can hold values beyond Y2038 */
void test_sessionTime_y2038(void)
{
/* Y2038 overflow point: 2^31 = 2147483648 */
uint64 y2038_overflow = 2147483648ULL;
uint64 max_uint32 = 4294967295ULL;
uint64 beyond_32bit = 5000000000ULL;

/* Simulate sessionTime field */
uint64 sessionTime;

sessionTime = y2038_overflow;
TEST_ASSERT(sessionTime == y2038_overflow,
"sessionTime can hold Y2038 overflow value (2^31)");

sessionTime = max_uint32;
TEST_ASSERT(sessionTime == max_uint32,
"sessionTime can hold max uint32 value (2^32-1)");

sessionTime = beyond_32bit;
TEST_ASSERT(sessionTime == beyond_32bit,
"sessionTime can hold value beyond 32-bit range");
}

/* Test that lastAuthTime can hold values beyond Y2038 */
void test_lastAuthTime_y2038(void)
{
/* Test lastAuthTime field */
uint64 lastAuthTime;

/* Y2038 overflow point */
lastAuthTime = 2147483648ULL;
TEST_ASSERT(lastAuthTime == 2147483648ULL,
"lastAuthTime can hold Y2038 overflow value");

/* Far future timestamp (~year 2128) */
lastAuthTime = 5000000000ULL;
TEST_ASSERT(lastAuthTime == 5000000000ULL,
"lastAuthTime can hold far future timestamp");

/* Max 64-bit value */
lastAuthTime = 0xFFFFFFFFFFFFFFFFULL;
TEST_ASSERT(lastAuthTime == 0xFFFFFFFFFFFFFFFFULL,
"lastAuthTime can hold max 64-bit value");
}

/* Test timestamp arithmetic doesn't overflow */
void test_timestamp_arithmetic_no_overflow(void)
{
uint64 timestamp1 = 2147483647ULL; /* Just before Y2038 overflow */
uint64 timestamp2 = 1000ULL;
uint64 result;

/* This would overflow with 32-bit arithmetic */
result = timestamp1 + timestamp2;
TEST_ASSERT(result == 2147484647ULL,
"Timestamp addition doesn't overflow at Y2038 boundary");

/* Test subtraction near Y2038 boundary */
timestamp1 = 2147483648ULL; /* Y2038 overflow point */
timestamp2 = 100ULL;
result = timestamp1 - timestamp2;
TEST_ASSERT(result == 2147483548ULL,
"Timestamp subtraction works correctly at Y2038 boundary");
}

/* Test timestamp comparison works correctly for large values */
void test_timestamp_comparison_large_values(void)
{
uint64 older = 2147483647ULL; /* Just before Y2038 */
uint64 newer = 2147483648ULL; /* Y2038 overflow point */

TEST_ASSERT(newer > older, "Timestamp comparison works across Y2038 boundary");
TEST_ASSERT(older < newer, "Timestamp less-than comparison works across Y2038 boundary");

/* Test with values far beyond 32-bit range */
older = 4294967295ULL; /* Max uint32 */
newer = 4294967296ULL; /* Just beyond uint32 max */
TEST_ASSERT(newer > older, "Timestamp comparison works beyond uint32 max");
}

/* Test session duration calculation with large timestamps */
void test_session_duration_calculation(void)
{
uint64 sessionStartTime = 2147483600ULL; /* Just before Y2038 */
uint64 currentTime = 2147483700ULL; /* After Y2038 overflow */
uint64 duration;

duration = currentTime - sessionStartTime;
TEST_ASSERT(duration == 100ULL,
"Session duration calculation works across Y2038 boundary");

/* Test with timestamps far in the future */
sessionStartTime = 5000000000ULL; /* ~year 2128 */
currentTime = 5000003600ULL; /* 1 hour later */
duration = currentTime - sessionStartTime;
TEST_ASSERT(duration == 3600ULL,
"Session duration calculation works with far future timestamps");
}

/* Test authentication timeout calculation */
void test_auth_timeout_calculation(void)
{
uint64 lastAuthTime = 2147483647ULL; /* Just before Y2038 */
uint64 sessionTimeout = 3600ULL; /* 1 hour timeout */
uint64 expirationTime;

expirationTime = lastAuthTime + sessionTimeout;
TEST_ASSERT(expirationTime == 2147487247ULL,
"Auth timeout calculation doesn't overflow at Y2038 boundary");

/* Verify the expiration time is correctly calculated */
uint64 currentTime = 2147483700ULL;
TEST_ASSERT(currentTime < expirationTime,
"Session is still valid after Y2038 boundary");
}

/* Simulate the authmgrClientInfo_t structure with Y2038-safe fields */
typedef struct test_authmgrClientInfo_s {
uint64 sessionTime; /* Y2038-safe */
uint32 clientTimeout;
uint32 sessionTimeout;
uint32 terminationAction;
uint64 lastAuthTime; /* Y2038-safe */
} test_authmgrClientInfo_t;

void test_struct_field_sizes(void)
{
test_authmgrClientInfo_t client;

/* Verify the Y2038-safe fields are 64-bit */
TEST_ASSERT(sizeof(client.sessionTime) == 8,
"sessionTime field is 64-bit in struct");
TEST_ASSERT(sizeof(client.lastAuthTime) == 8,
"lastAuthTime field is 64-bit in struct");

/* Verify other fields remain 32-bit */
TEST_ASSERT(sizeof(client.clientTimeout) == 4,
"clientTimeout field remains 32-bit");
TEST_ASSERT(sizeof(client.sessionTimeout) == 4,
"sessionTimeout field remains 32-bit");
}

void test_struct_operations_y2038(void)
{
test_authmgrClientInfo_t client;

/* Initialize with Y2038-safe values */
client.sessionTime = 2147483648ULL; /* Y2038 overflow point */
client.lastAuthTime = 2147483700ULL;
client.sessionTimeout = 3600;

/* Verify values are stored correctly */
TEST_ASSERT(client.sessionTime == 2147483648ULL,
"Struct sessionTime stores Y2038 value correctly");
TEST_ASSERT(client.lastAuthTime == 2147483700ULL,
"Struct lastAuthTime stores Y2038 value correctly");

/* Test session duration calculation using struct fields */
uint64 duration = client.lastAuthTime - client.sessionTime;
TEST_ASSERT(duration == 52ULL,
"Session duration from struct fields calculated correctly");
}

int main(void)
{
printf("=== Y2038 Timestamp Overflow Unit Tests for sonic-pac ===\n\n");

test_uint64_type_size();
test_sessionTime_y2038();
test_lastAuthTime_y2038();
test_timestamp_arithmetic_no_overflow();
test_timestamp_comparison_large_values();
test_session_duration_calculation();
test_auth_timeout_calculation();
test_struct_field_sizes();
test_struct_operations_y2038();

printf("\n=== Test Summary ===\n");
printf("Passed: %d\n", tests_passed);
printf("Failed: %d\n", tests_failed);
printf("Total: %d\n", tests_passed + tests_failed);

return tests_failed > 0 ? 1 : 0;
}