summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Larson <[email protected]>2021-01-07 18:16:40 -0800
committerScott Larson <[email protected]>2021-01-07 18:16:40 -0800
commit699d64dc5e4ef6cedd42401bc10cf9f3be0b476b (patch)
treed0e31ccb944f81f30b83184b49f19dd337cc5adc
parentf66451ca193a96b5734e9a99d6d0ed9de44c9ac5 (diff)
update to v6.1.3
-rwxr-xr-xREADME.md2
-rw-r--r--addons/CMakeLists.txt4
m---------addons/azure_iot/azure-sdk-for-c0
-rw-r--r--addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c2
-rw-r--r--addons/azure_iot/docs/azure_rtos_iot_hub_client.md2
-rw-r--r--addons/azure_iot/nx_azure_iot_hub_client.c14
-rw-r--r--addons/azure_iot/nx_azure_iot_hub_client.h2
-rw-r--r--addons/azure_iot/nx_azure_iot_provisioning_client.c11
-rw-r--r--addons/dhcp/nxd_dhcp_server.c13
-rw-r--r--addons/dns/nxd_dns.c88
-rw-r--r--addons/dns/nxd_dns.h10
-rw-r--r--addons/ftp/nxd_ftp_server.c158
-rw-r--r--addons/mdns/nxd_mdns.c74
-rw-r--r--addons/mdns/nxd_mdns.h11
-rw-r--r--addons/pppoe/nx_pppoe_client.c88
-rw-r--r--addons/pppoe/nx_pppoe_client.h7
-rw-r--r--addons/ptp/nxd_ptp_client.c3736
-rw-r--r--addons/ptp/nxd_ptp_client.h482
-rw-r--r--common/inc/nx_api.h12
-rw-r--r--common/src/nx_ipv6_process_hop_by_hop_option.c13
-rw-r--r--common/src/nx_utility.c90
-rw-r--r--nx_secure/inc/nx_secure_dtls.h10
-rw-r--r--nx_secure/inc/nx_secure_tls.h11
-rw-r--r--nx_secure/src/nx_secure_dtls_client_handshake.c22
-rw-r--r--nx_secure/src/nx_secure_dtls_process_clienthello.c12
-rw-r--r--nx_secure/src/nx_secure_dtls_process_handshake_header.c18
-rw-r--r--nx_secure/src/nx_secure_dtls_process_record.c8
-rw-r--r--nx_secure/src/nx_secure_dtls_server_handshake.c19
-rw-r--r--nx_secure/src/nx_secure_tls_1_3_client_handshake.c17
-rw-r--r--nx_secure/src/nx_secure_tls_1_3_server_handshake.c17
-rw-r--r--nx_secure/src/nx_secure_tls_client_handshake.c17
-rw-r--r--nx_secure/src/nx_secure_tls_process_handshake_header.c17
-rw-r--r--nx_secure/src/nx_secure_tls_server_handshake.c17
-rw-r--r--ports/cortex_m23/ac5/inc/nx_port.h210
-rw-r--r--ports/cortex_m23/gnu/inc/nx_port.h199
-rw-r--r--ports/cortex_m23/iar/inc/nx_port.h190
-rw-r--r--ports/cortex_m33/ac5/inc/nx_port.h210
-rw-r--r--ports/cortex_m33/gnu/inc/nx_port.h199
-rw-r--r--ports/cortex_m33/iar/inc/nx_port.h190
-rw-r--r--ports/rxv2/ccrx/inc/nx_port.h221
-rw-r--r--ports/rxv2/gnu/inc/nx_port.h210
-rw-r--r--ports/rxv2/iar/inc/nx_port.h210
-rw-r--r--samples/demo_netx_duo_ptp_client.c271
43 files changed, 6964 insertions, 150 deletions
diff --git a/README.md b/README.md
index 5e2579a4..c532a75c 100755
--- a/README.md
+++ b/README.md
@@ -96,4 +96,4 @@ The following are references to additional Azure RTOS and Azure IoT in general:
| Azure RTOS Sales Questions: | https://azure-rtos.ms-iot-contact.com/ |
| Microsoft Q/A for Azure IoT: | https://docs.microsoft.com/en-us/answers/products/azure?product=iot |
| Internet of Things Show: | https://aka.ms/iotshow |
-| IoT Tech Community: | https://aka.ms/iottechcommunity |
+| IoT Tech Community: | https://aka.ms/iottechcommunity | \ No newline at end of file
diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt
index cfe60389..39c80e95 100644
--- a/addons/CMakeLists.txt
+++ b/addons/CMakeLists.txt
@@ -14,6 +14,7 @@ set(SOURCES
${CMAKE_CURRENT_LIST_DIR}/ftp/nxd_ftp_server.c
${CMAKE_CURRENT_LIST_DIR}/http/nxd_http_client.c
${CMAKE_CURRENT_LIST_DIR}/http/nxd_http_server.c
+ ${CMAKE_CURRENT_LIST_DIR}/lwm2m/nx_lwm2m_client.c
${CMAKE_CURRENT_LIST_DIR}/mdns/nxd_mdns.c
${CMAKE_CURRENT_LIST_DIR}/mqtt/nxd_mqtt_client.c
${CMAKE_CURRENT_LIST_DIR}/nat/nx_nat.c
@@ -21,6 +22,7 @@ set(SOURCES
${CMAKE_CURRENT_LIST_DIR}/ppp/nx_ppp.c
${CMAKE_CURRENT_LIST_DIR}/pppoe/nx_pppoe_client.c
${CMAKE_CURRENT_LIST_DIR}/pppoe/nx_pppoe_server.c
+ ${CMAKE_CURRENT_LIST_DIR}/ptp/nxd_ptp_client.c
${CMAKE_CURRENT_LIST_DIR}/smtp/nxd_smtp_client.c
${CMAKE_CURRENT_LIST_DIR}/snmp/nx_des.c
${CMAKE_CURRENT_LIST_DIR}/snmp/nx_sha1.c
@@ -84,12 +86,14 @@ target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/dns
${CMAKE_CURRENT_LIST_DIR}/ftp
${CMAKE_CURRENT_LIST_DIR}/http
+ ${CMAKE_CURRENT_LIST_DIR}/lwm2m
${CMAKE_CURRENT_LIST_DIR}/mdns
${CMAKE_CURRENT_LIST_DIR}/mqtt
${CMAKE_CURRENT_LIST_DIR}/nat
${CMAKE_CURRENT_LIST_DIR}/pop3
${CMAKE_CURRENT_LIST_DIR}/ppp
${CMAKE_CURRENT_LIST_DIR}/pppoe
+ ${CMAKE_CURRENT_LIST_DIR}/ptp
${CMAKE_CURRENT_LIST_DIR}/smtp
${CMAKE_CURRENT_LIST_DIR}/snmp
${CMAKE_CURRENT_LIST_DIR}/sntp
diff --git a/addons/azure_iot/azure-sdk-for-c b/addons/azure_iot/azure-sdk-for-c
-Subproject 5e9d7b96dbd98ce7125e4beed385959a32b4c6c
+Subproject c305408ce67e98e1417bb7518ae2743b8c397ec
diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c
index b148e535..08d48a7a 100644
--- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c
+++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c
@@ -123,7 +123,7 @@ asc_result_t core_collect(core_t *core_ptr)
current_collector=current_collector->next
) {
uint32_t last_collected = collector_get_last_collected_timestamp(current_collector);
- double interval = priority_collectors_get_interval(prioritized_collectors);
+ uint32_t interval = priority_collectors_get_interval(prioritized_collectors);
if (current_snapshot - last_collected >= interval) {
time_passed = true;
diff --git a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md
index ea912887..2fcdba02 100644
--- a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md
+++ b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md
@@ -167,7 +167,7 @@ UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_pt
```
**Description**
-<p>This routine sets the Device Twin model id. Note: THIS FUNCTION IS TEMPORARY. IT IS SUBJECT TO CHANGE OR BE REMOVED IN THE FUTURE.</p>
+<p>This routine sets the Device Twin model id.</p>
**Parameters**
diff --git a/addons/azure_iot/nx_azure_iot_hub_client.c b/addons/azure_iot/nx_azure_iot_hub_client.c
index 3cdff666..0b15d58e 100644
--- a/addons/azure_iot/nx_azure_iot_hub_client.c
+++ b/addons/azure_iot/nx_azure_iot_hub_client.c
@@ -302,7 +302,7 @@ az_result core_result;
/* Build client id. */
buffer_length = buffer_size;
core_result = az_iot_hub_client_get_client_id(&(hub_client_ptr -> iot_hub_client_core),
- (CHAR *)buffer_ptr, buffer_length, &buffer_length);
+ (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length);
if (az_result_failed(core_result))
{
@@ -322,7 +322,7 @@ az_result core_result;
/* Build user name. */
buffer_length = buffer_size;
core_result = az_iot_hub_client_get_user_name(&hub_client_ptr -> iot_hub_client_core,
- (CHAR *)buffer_ptr, buffer_length, &buffer_length);
+ (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length);
if (az_result_failed(core_result))
{
@@ -786,7 +786,7 @@ az_result core_result;
topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr);
core_result = az_iot_hub_client_telemetry_get_publish_topic(&hub_client_ptr -> iot_hub_client_core,
NULL, (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
- topic_length, &topic_length);
+ topic_length, (size_t *)&topic_length);
if (az_result_failed(core_result))
{
LogError(LogLiteralArgs("IoTHub client telemetry message create fail with error status: %d"), core_result);
@@ -1569,7 +1569,7 @@ USHORT length;
core_result = az_iot_hub_client_twin_patch_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
- buffer_size, &topic_length);
+ buffer_size, (size_t *)&topic_length);
if (az_result_failed(core_result))
{
LogError(LogLiteralArgs("IoTHub client reported state send fail: NX_AZURE_IOT_HUB_CLIENT_TOPIC_SIZE is too small."));
@@ -1741,7 +1741,7 @@ az_result core_result;
core_result = az_iot_hub_client_twin_document_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
- buffer_size, &topic_length);
+ buffer_size, (size_t *)&topic_length);
if (az_result_failed(core_result))
{
LogError(LogLiteralArgs("IoTHub client device twin get topic fail."));
@@ -2429,7 +2429,7 @@ az_result core_result;
buffer_span = az_span_create(output_ptr, (INT)output_len);
core_result= az_iot_hub_client_sas_get_password(&(hub_client_ptr -> iot_hub_client_core),
expiry_time_secs, buffer_span, AZ_SPAN_EMPTY,
- (CHAR *)sas_buffer, sas_buffer_len, &sas_buffer_len);
+ (CHAR *)sas_buffer, sas_buffer_len, (size_t *)&sas_buffer_len);
if (az_result_failed(core_result))
{
LogError(LogLiteralArgs("IoTHub failed to generate token with error status: %d"), core_result);
@@ -2622,7 +2622,7 @@ az_result core_result;
core_result = az_iot_hub_client_methods_response_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
request_id_span, (USHORT)status_code,
(CHAR *)packet_ptr -> nx_packet_prepend_ptr,
- topic_length, &topic_length);
+ topic_length, (size_t *)&topic_length);
if (az_result_failed(core_result))
{
LogError(LogLiteralArgs("Failed to create the method response topic"));
diff --git a/addons/azure_iot/nx_azure_iot_hub_client.h b/addons/azure_iot/nx_azure_iot_hub_client.h
index a510bb81..69a5348a 100644
--- a/addons/azure_iot/nx_azure_iot_hub_client.h
+++ b/addons/azure_iot/nx_azure_iot_hub_client.h
@@ -227,8 +227,6 @@ UINT nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT *hub_clie
/**
* @brief Set Device Twin model id in the IoT Hub client.
*
- * @warning THIS FUNCTION IS TEMPORARY. IT IS SUBJECT TO CHANGE OR BE REMOVED IN THE FUTURE.
- *
* @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT.
* @param[in] model_id_ptr A pointer to a model id.
* @param[in] model_id_length Length of `model id`.
diff --git a/addons/azure_iot/nx_azure_iot_provisioning_client.c b/addons/azure_iot/nx_azure_iot_provisioning_client.c
index 78a4d014..3ab6fb2f 100644
--- a/addons/azure_iot/nx_azure_iot_provisioning_client.c
+++ b/addons/azure_iot/nx_azure_iot_provisioning_client.c
@@ -638,13 +638,15 @@ az_result core_result;
if (register_response == NULL)
{
core_result = az_iot_provisioning_client_register_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
- (CHAR *)buffer_ptr, buffer_size, &mqtt_topic_length);
+ (CHAR *)buffer_ptr, buffer_size,
+ (size_t *)&mqtt_topic_length);
}
else
{
core_result = az_iot_provisioning_client_query_status_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
register_response -> operation_id, (CHAR *)buffer_ptr,
- buffer_size, &mqtt_topic_length);
+ buffer_size,
+ (size_t *)&mqtt_topic_length);
}
if (az_result_failed(core_result))
@@ -772,7 +774,7 @@ az_span policy_name = AZ_SPAN_LITERAL_FROM_STR(NX_AZURE_IOT_PROVISIONING_CLIENT_
buffer_span, expiry_time_secs, policy_name,
(CHAR *)resource_ptr -> resource_mqtt_sas_token,
prov_client_ptr -> nx_azure_iot_provisioning_client_sas_token_buff_size,
- &(resource_ptr -> resource_mqtt_sas_token_length));
+ (size_t *)&(resource_ptr -> resource_mqtt_sas_token_length));
if (az_result_failed(core_result))
{
LogError(LogLiteralArgs("IoTProvisioning failed to generate token with error : %d"), core_result);
@@ -892,7 +894,8 @@ az_span registration_id_span = az_span_create((UCHAR *)registration_id, (INT)reg
/* Build user name. */
if (az_result_failed(az_iot_provisioning_client_get_user_name(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
- (CHAR *)buffer_ptr, buffer_size, &mqtt_user_name_length)))
+ (CHAR *)buffer_ptr, buffer_size,
+ (size_t *)&mqtt_user_name_length)))
{
LogError(LogLiteralArgs("IoTProvisioning client connect fail: NX_AZURE_IOT_Provisioning_CLIENT_USERNAME_SIZE is too small."));
nx_azure_iot_buffer_free(buffer_context);
diff --git a/addons/dhcp/nxd_dhcp_server.c b/addons/dhcp/nxd_dhcp_server.c
index 4c02ad5f..90143562 100644
--- a/addons/dhcp/nxd_dhcp_server.c
+++ b/addons/dhcp/nxd_dhcp_server.c
@@ -2558,7 +2558,7 @@ CHAR *work_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcp_parse_next_option PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2581,7 +2581,7 @@ CHAR *work_ptr;
/* */
/* CALLS */
/* */
-/* atoi Convert ascii number to integer*/
+/* _nx_utility_string_to_uint Convert ascii number to integer*/
/* */
/* CALLED BY */
/* */
@@ -2594,6 +2594,9 @@ CHAR *work_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), fixed */
+/* obsolescent functions, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_dhcp_parse_next_option(CHAR **option_list, UINT *option, UINT length)
@@ -2656,10 +2659,8 @@ CHAR *buffer;
*option_list += j;
- /* Convert the number string to an actual integer. */
- *option = (UINT) atoi(num_string);
-
- return(NX_SUCCESS);
+ /* Convert the number string to an actual unsigned integer. */
+ return(_nx_utility_string_to_uint(num_string, buffer_index, option));
}
diff --git a/addons/dns/nxd_dns.c b/addons/dns/nxd_dns.c
index 9726beff..64bd6180 100644
--- a/addons/dns/nxd_dns.c
+++ b/addons/dns/nxd_dns.c
@@ -67,7 +67,7 @@ static UINT _nx_dns_process_a_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr
static UINT _nx_dns_process_aaaa_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, UCHAR **buffer_append_ptr, UINT *record_count, UINT rr_location);
#ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
-static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start);
+static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start, UINT data_length);
static UINT _nx_dns_process_cname_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count);
static UINT _nx_dns_process_txt_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count);
static UINT _nx_dns_process_ns_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, UCHAR **buffer_append_ptr, UINT *record_count);
@@ -6175,7 +6175,7 @@ ULONG rr_ttl;
/* FUNCTION RELEASE */
/* */
/* _nx_dns_process_ns_type PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6222,6 +6222,10 @@ ULONG rr_ttl;
/* updated resource get APIs to*/
/* improve buffer bound check, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Updated input parameter of the*/
+/* API to get the real size of */
+/* resource name, resulting in */
+/* version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_dns_process_ns_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr,
@@ -6291,7 +6295,7 @@ ULONG rr_ttl;
}
/* Get the real size of the name, and set the name buffer size.*/
- name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr));
+ name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length);
/* Check the buffer space. */
if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_NS_ENTRY)))
@@ -6378,7 +6382,7 @@ ULONG rr_ttl;
/* FUNCTION RELEASE */
/* */
/* _nx_dns_process_mx_type PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6426,6 +6430,10 @@ ULONG rr_ttl;
/* updated resource get APIs to*/
/* improve buffer bound check, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Updated input parameter of the*/
+/* API to get the real size of */
+/* resource name, resulting in */
+/* version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_dns_process_mx_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr,
@@ -6504,7 +6512,7 @@ UINT size;
data_ptr += 2;
/* Get the real size of the name, and set the name buffer size.*/
- name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr));
+ name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length);
/* Check the buffer space. */
if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_MX_ENTRY)))
@@ -6609,7 +6617,7 @@ UINT size;
/* FUNCTION RELEASE */
/* */
/* _nx_dns_process_srv_type PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6657,6 +6665,10 @@ UINT size;
/* updated resource get APIs to*/
/* improve buffer bound check, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Updated input parameter of the*/
+/* API to get the real size of */
+/* resource name, resulting in */
+/* version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_dns_process_srv_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr,
@@ -6748,7 +6760,7 @@ UINT size;
data_ptr += 2;
/* Get the real size of the name, and set the name buffer size.*/
- name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr));
+ name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length);
/* Check the buffer space. */
if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_MX_ENTRY)))
@@ -8108,7 +8120,7 @@ UINT count = 1;
/* FUNCTION RELEASE */
/* */
/* _nx_dns_name_string_unencode PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -8146,6 +8158,10 @@ UINT count = 1;
/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
/* compression pointer check, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), prevented*/
+/* infinite loop in name */
+/* compression, resulting in */
+/* version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_dns_name_string_unencode(NX_PACKET *packet_ptr, UCHAR *data, UCHAR *buffer, UINT buffer_size)
@@ -8156,7 +8172,8 @@ UCHAR *message_start;
UINT label_size;
UINT offset;
UINT length;
-
+UINT pointer_count = 0;
+
/* Initialize the value. */
character = data;
message_start = packet_ptr -> nx_packet_prepend_ptr;
@@ -8218,6 +8235,14 @@ UINT length;
}
else
{
+ /* Prevent infinite loop with compression pointers. */
+ pointer_count++;
+ if (pointer_count > NX_DNS_MAX_COMPRESSION_POINTERS)
+ {
+
+ /* This is malformed packet. */
+ return(0);
+ }
/* update valid pointer */
character = message_start + offset;
}
@@ -8354,7 +8379,7 @@ UINT size = 0;
/* FUNCTION RELEASE */
/* */
/* _nx_dns_resource_name_real_size_calculate PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -8367,6 +8392,7 @@ UINT size = 0;
/* */
/* data Pointer to buffer to decode */
/* start Location of start of data */
+/* data_length Data buffer length */
/* */
/* OUTPUT */
/* */
@@ -8388,14 +8414,20 @@ UINT size = 0;
/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
/* compression pointer check, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* pointer check, prevented */
+/* infinite loop in name */
+/* compression, resulting in */
+/* version 6.1.3 */
/* */
/**************************************************************************/
-static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start)
+static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start, UINT data_length)
{
UCHAR *character = data + start;
UINT length = 0;
-
+UINT offset;
+UINT pointer_count = 0;
/* As long as there is space in the buffer and we haven't
found a zero terminating label */
@@ -8422,8 +8454,18 @@ UINT length = 0;
else if ((labelSize & NX_DNS_COMPRESS_MASK) == NX_DNS_COMPRESS_VALUE)
{
+ /* Get the offset. */
+ offset = ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character;
+
+ /* Check the offset. */
+ if (offset >= data_length)
+ {
+
+ return(0);
+ }
+
/* This is a pointer, just adjust the source. */
- if (character == data + ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character)
+ if (character == data + offset)
{
/* If compression pointer equals the same offset currently being parsed,
it could lead to an infinite loop. */
@@ -8431,8 +8473,19 @@ UINT length = 0;
}
else
{
+
+ /* Prevent infinite loop with compression pointers. */
+ pointer_count++;
+
+ if (pointer_count > NX_DNS_MAX_COMPRESSION_POINTERS)
+ {
+
+ /* This is malformed packet. */
+ return(0);
+ }
+
/* update valid pointer */
- character = data + ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character;
+ character = data + offset;
}
}
else
@@ -8442,9 +8495,12 @@ UINT length = 0;
return(0);
}
}
-
+
/* Reduce the last '.' string, update the length. */
- length --;
+ if (length)
+ {
+ length --;
+ }
/* Return name size. */
return(length);
diff --git a/addons/dns/nxd_dns.h b/addons/dns/nxd_dns.h
index c529db8d..39ea0045 100644
--- a/addons/dns/nxd_dns.h
+++ b/addons/dns/nxd_dns.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nxd_dns.h PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -45,6 +45,10 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), prevented*/
+/* infinite loop in name */
+/* compression, resulting in */
+/* version 6.1.3 */
/* */
/**************************************************************************/
@@ -295,6 +299,10 @@ extern "C" {
#define NX_DNS_PACKET_ALLOCATE_TIMEOUT NX_IP_PERIODIC_RATE
#endif
+/* Define the maximum number of pointers allowed in name compression. */
+#ifndef NX_DNS_MAX_COMPRESSION_POINTERS
+#define NX_DNS_MAX_COMPRESSION_POINTERS 16
+#endif
/* Define the basic DNS data structure. */
diff --git a/addons/ftp/nxd_ftp_server.c b/addons/ftp/nxd_ftp_server.c
index 6bedfa4c..f7071a70 100644
--- a/addons/ftp/nxd_ftp_server.c
+++ b/addons/ftp/nxd_ftp_server.c
@@ -1523,7 +1523,7 @@ ULONG events;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_command_process PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1595,6 +1595,9 @@ ULONG events;
/* packet length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
VOID _nx_ftp_server_command_process(NX_FTP_SERVER *ftp_server_ptr)
@@ -1942,6 +1945,18 @@ ULONG block_size;
break;
}
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "File Open Fail");
+ break;
+ }
+
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -2223,6 +2238,18 @@ ULONG block_size;
break;
}
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "File Open Failed");
+ break;
+ }
+
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -2401,6 +2428,18 @@ ULONG block_size;
case NX_FTP_RNFR:
{
+
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Rename File not found");
+ break;
+ }
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -2467,6 +2506,18 @@ ULONG block_size;
case NX_FTP_RNTO:
{
+
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Rename failed");
+ break;
+ }
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -2537,6 +2588,18 @@ ULONG block_size;
case NX_FTP_DELE:
{
+
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Delete Failed");
+ break;
+ }
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -2593,6 +2656,18 @@ ULONG block_size;
case NX_FTP_RMD:
{
+
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Delete Directory Fail");
+ break;
+ }
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -2655,6 +2730,18 @@ ULONG block_size;
case NX_FTP_MKD:
{
+
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Directory Create failed");
+ break;
+ }
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -2761,6 +2848,18 @@ ULONG block_size;
break;
}
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "List bad Directory");
+ break;
+ }
+
/* Change to the default directory of this connection. */
fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -3134,6 +3233,18 @@ ULONG block_size;
break;
}
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Bad Directory");
+ break;
+ }
+
/* Change to the default directory of this connection. */
status = fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
@@ -4113,6 +4224,9 @@ ULONG block_size;
/* If CDUP command, create the "up one directory" pathname string. */
if (ftp_command == NX_FTP_CDUP)
{
+
+ /* Move the pointer to make sure there is enough memory to store the data. */
+ buffer_ptr -= 3;
buffer_ptr[0] = '.';
buffer_ptr[1] = '.';
buffer_ptr[2] = NX_NULL;
@@ -4122,6 +4236,18 @@ ULONG block_size;
else
{
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Change Dir Fail");
+ break;
+ }
+
/* Find the end of the message. */
j = 0;
while (j < packet_ptr -> nx_packet_length - 1)
@@ -4993,7 +5119,7 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_parse_command PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5027,6 +5153,9 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_ftp_server_parse_command(NX_PACKET *packet_ptr)
@@ -5036,6 +5165,14 @@ UINT i;
char *buffer_ptr;
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message, just return INVALID. */
+ return(NX_FTP_INVALID);
+ }
+
/* Setup pointer to command buffer area. */
buffer_ptr = (char *) packet_ptr -> nx_packet_prepend_ptr;
@@ -5719,7 +5856,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_utility_parse_IPv6_address PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5763,6 +5900,9 @@ UINT status;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* colons count verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_ftp_utility_parse_IPv6_address(CHAR *buffer_ptr, UINT buffer_length, NXD_ADDRESS *ipduo_address)
@@ -5898,6 +6038,12 @@ ULONG temp;
else if (buffer_ptr[j] == ':')
{
+ /* Check if colons is valid. */
+ if (colons >= 7)
+ {
+ return NX_FTP_INVALID_ADDRESS;
+ }
+
/* Increment the colon count. */
colons++;
@@ -5963,6 +6109,12 @@ ULONG temp;
m++;
}
+ /* Check if colons is valid. */
+ if (actual_colons_left >= remaining_colons)
+ {
+ return NX_FTP_INVALID_ADDRESS;
+ }
+
/* Compute the number of zeros to insert into the NXD_ADDRESS IPv6 ULONG array. */
number_consecutive_zeros_to_add = remaining_colons - actual_colons_left;
diff --git a/addons/mdns/nxd_mdns.c b/addons/mdns/nxd_mdns.c
index 4439cfe0..3f037904 100644
--- a/addons/mdns/nxd_mdns.c
+++ b/addons/mdns/nxd_mdns.c
@@ -85,7 +85,7 @@ static UINT _nx_mdns_rr_size_get(UCHAR *resource);
static UINT _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length);
static UINT _nx_mdns_name_size_calculate(UCHAR *name);
static UINT _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name);
-static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UCHAR *buffer, UINT size);
+static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size);
static UINT _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *name);
static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size);
static VOID _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value);
@@ -9632,7 +9632,7 @@ UINT rr_name_length;
/* FUNCTION RELEASE */
/* */
/* _nx_mdns_packet_rr_set PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -9671,6 +9671,9 @@ UINT rr_name_length;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index)
@@ -9713,8 +9716,9 @@ UINT temp_string_length;
/* Process the name string. */
if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
- (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
- temp_string_buffer, NX_MDNS_NAME_MAX))
+ (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
+ packet_ptr -> nx_packet_length,
+ temp_string_buffer, NX_MDNS_NAME_MAX))
{
/* Check string length. */
@@ -9776,7 +9780,7 @@ UINT temp_string_length;
/* FUNCTION RELEASE */
/* */
/* _nx_mdns_packet_rr_process PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -9818,6 +9822,9 @@ UINT temp_string_length;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index)
@@ -9847,8 +9854,9 @@ UINT rr_name_length;
/* Process the name string. */
if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
- (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
- temp_string_buffer, NX_MDNS_NAME_MAX))
+ (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
+ packet_ptr -> nx_packet_length,
+ temp_string_buffer, NX_MDNS_NAME_MAX))
{
/* Check string length. */
@@ -10079,7 +10087,7 @@ UINT rr_name_length;
/* FUNCTION RELEASE */
/* */
/* _nx_mdns_packet_rr_data_set PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -10121,6 +10129,9 @@ UINT rr_name_length;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op)
@@ -10285,7 +10296,8 @@ UINT temp_string_length;
/* Process the target/domain name string. */
if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
- (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
+ (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
+ packet_ptr -> nx_packet_length,
temp_string_buffer, NX_MDNS_NAME_MAX))
{
@@ -13567,7 +13579,7 @@ UINT count = 1;
/* FUNCTION RELEASE */
/* */
/* _nx_mdns_txt_string_decode PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -13605,6 +13617,9 @@ UINT count = 1;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size)
@@ -13628,7 +13643,7 @@ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buf
{
/* Simple count, check for space and copy the label. */
- while (labelSize > 0)
+ while ((labelSize > 0) && (data_length > 1))
{
*buffer++ = *data++;
@@ -13842,7 +13857,7 @@ UINT count = 1;
/* FUNCTION RELEASE */
/* */
/* _nx_mdns_name_string_decode PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -13857,6 +13872,7 @@ UINT count = 1;
/* */
/* data Pointer to buffer to decode */
/* start Location of start of data */
+/* data_length Length of data buffer */
/* buffer Pointer to decoded data */
/* size Size of data buffer to decode */
/* */
@@ -13878,13 +13894,20 @@ UINT count = 1;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* buffer length verification, */
+/* prevented infinite loop in */
+/* name compression, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
-static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UCHAR *buffer, UINT size)
+static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size)
{
UCHAR *character = data + start;
UINT length = 0;
+UINT offset;
+UINT pointer_count = 0;
/* As long as there is space in the buffer and we haven't
@@ -13915,7 +13938,28 @@ UINT length = 0;
{
/* This is a pointer, just adjust the source. */
- character = data + ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character;
+ offset = ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character;
+
+ /* Make sure offset is in the buffer. */
+ if (offset >= data_length)
+ {
+ return(0);
+ }
+
+ /* Pointer must not point back to itself. */
+ if ((data + offset == character) || (data + offset == character - 1))
+ {
+ return(0);
+ }
+
+ /* Prevent infinite loop with compression pointers. */
+ pointer_count++;
+ if (pointer_count > NX_MDNS_MAX_COMPRESSION_POINTERS)
+ {
+ return(0);
+ }
+
+ character = data + offset;
}
else
{
@@ -13926,7 +13970,7 @@ UINT length = 0;
}
/* Done copying the data, set the last . to a trailing null */
- if (*(buffer - 1) == '.')
+ if ((length > 0) && (*(buffer - 1) == '.'))
{
buffer--;
diff --git a/addons/mdns/nxd_mdns.h b/addons/mdns/nxd_mdns.h
index 9f0faa6b..3287ab2c 100644
--- a/addons/mdns/nxd_mdns.h
+++ b/addons/mdns/nxd_mdns.h
@@ -25,7 +25,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nxd_mdns.h PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -45,6 +45,10 @@
/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
/* buffer length verification, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), */
+/* prevented infinite loop in */
+/* name compression, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -378,6 +382,11 @@ extern "C" {
#define NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT NX_IP_PERIODIC_RATE
#endif /* NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT */
+/* Define the maximum number of pointers allowed in name compression. */
+#ifndef NX_MDNS_MAX_COMPRESSION_POINTERS
+#define NX_MDNS_MAX_COMPRESSION_POINTERS 16
+#endif /* NX_MDNS_MAX_COMPRESSION_POINTERS */
+
/* Define the default mDNS's announcing value. */
#define NX_MDNS_ANNOUNCING_PERIOD NX_IP_PERIODIC_RATE
diff --git a/addons/pppoe/nx_pppoe_client.c b/addons/pppoe/nx_pppoe_client.c
index 7959cd0f..38ebaa8a 100644
--- a/addons/pppoe/nx_pppoe_client.c
+++ b/addons/pppoe/nx_pppoe_client.c
@@ -609,7 +609,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_client_service_name_set_extended PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -650,6 +650,9 @@ UINT status;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* string length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_pppoe_client_service_name_set_extended(NX_PPPOE_CLIENT *pppoe_client_ptr, UCHAR *service_name, UINT service_name_length)
@@ -671,6 +674,9 @@ UINT temp_service_name_length = 0;
/* Setup service name pointer. */
pppoe_client_ptr -> nx_pppoe_service_name = service_name;
+ /* Setup service name length. */
+ pppoe_client_ptr -> nx_pppoe_service_name_length = service_name_length;
+
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
@@ -869,7 +875,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_client_host_uniq_set_extended PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -910,6 +916,9 @@ UINT status;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* string length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_pppoe_client_host_uniq_set_extended(NX_PPPOE_CLIENT *pppoe_client_ptr, UCHAR *host_uniq, UINT host_uniq_length)
@@ -927,8 +936,11 @@ UINT temp_host_uniq_length = 0;
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
- /* Setup service name pointer. */
+ /* Setup host unique pointer. */
pppoe_client_ptr -> nx_pppoe_host_uniq = host_uniq;
+
+ /* Setup host unique length. */
+ pppoe_client_ptr -> nx_pppoe_host_uniq_length = host_uniq_length;
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
@@ -2160,7 +2172,7 @@ UINT ethernet_type;
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_client_discovery_packet_process PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2203,6 +2215,9 @@ UINT ethernet_type;
/* packet length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* string length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
VOID _nx_pppoe_client_discovery_packet_process(NX_PPPOE_CLIENT *pppoe_client_ptr, NX_PACKET *packet_ptr, ULONG server_mac_msw, ULONG server_mac_lsw)
@@ -2367,7 +2382,8 @@ UINT tag_host_uniq_valid = NX_FALSE;
{
/* Compare the service name with PPPoE Service name that Client is requesting. */
- if (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_service_name, tag_length))
+ if ((pppoe_client_ptr -> nx_pppoe_service_name_length == tag_length) &&
+ (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_service_name, tag_length)))
{
/* Update the information. */
@@ -2407,7 +2423,8 @@ UINT tag_host_uniq_valid = NX_FALSE;
tag_host_uniq_count ++;
/* Check the Host-Uniq. */
- if (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_host_uniq, tag_length))
+ if ((pppoe_client_ptr -> nx_pppoe_host_uniq_length == tag_length) &&
+ (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_host_uniq, tag_length)))
{
/* Update the information. */
@@ -2754,7 +2771,7 @@ NX_PPPOE_SERVER_SESSION *server_session_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_client_discovery_send PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2796,6 +2813,9 @@ NX_PPPOE_SERVER_SESSION *server_session_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* string length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
static UINT _nx_pppoe_client_discovery_send(NX_PPPOE_CLIENT *pppoe_client_ptr, UINT code)
@@ -2806,7 +2826,6 @@ NX_PACKET *packet_ptr;
UCHAR *work_ptr;
UINT status;
UINT index = 0;
-UINT tag_length;
/* Allocate a PPPoE packet. */
@@ -2846,21 +2865,12 @@ UINT tag_length;
if (pppoe_client_ptr -> nx_pppoe_service_name)
{
- /* Calculate the name length. */
- if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH))
- {
-
- /* Packet too small. */
- nx_packet_release(packet_ptr);
- return(NX_PPPOE_CLIENT_SERVICE_NAME_ERROR);
- }
-
if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >=
- (4 + tag_length))
+ (4 + pppoe_client_ptr -> nx_pppoe_service_name_length))
{
/* Added the Service-Name tag. */
- _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, tag_length, pppoe_client_ptr -> nx_pppoe_service_name, &index);
+ _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, pppoe_client_ptr -> nx_pppoe_service_name_length, pppoe_client_ptr -> nx_pppoe_service_name, &index);
}
else
{
@@ -2881,21 +2891,12 @@ UINT tag_length;
if (pppoe_client_ptr -> nx_pppoe_host_uniq)
{
- /* Calculate the name length. */
- if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_host_uniq), &tag_length, NX_MAX_STRING_LENGTH))
- {
-
- /* Packet too small. */
- nx_packet_release(packet_ptr);
- return(NX_PPPOE_CLIENT_PACKET_PAYLOAD_ERROR);
- }
-
if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >=
- (4 + tag_length))
+ (4 + pppoe_client_ptr -> nx_pppoe_host_uniq_length))
{
/* Added the Host-Uniq tag. */
- _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, tag_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index);
+ _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, pppoe_client_ptr -> nx_pppoe_host_uniq_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index);
}
else
{
@@ -2914,22 +2915,12 @@ UINT tag_length;
if (pppoe_client_ptr -> nx_pppoe_service_name)
{
-
- /* Calculate the name length. */
- if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH))
- {
-
- /* Packet too small. */
- nx_packet_release(packet_ptr);
- return(NX_PPPOE_CLIENT_SERVICE_NAME_ERROR);
- }
-
if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >=
- (4 + tag_length))
+ (4 + pppoe_client_ptr -> nx_pppoe_service_name_length))
{
/* Added the Service-Name tag. */
- _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, tag_length, pppoe_client_ptr -> nx_pppoe_service_name, &index);
+ _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, pppoe_client_ptr -> nx_pppoe_service_name_length, pppoe_client_ptr -> nx_pppoe_service_name, &index);
}
else
{
@@ -2950,21 +2941,12 @@ UINT tag_length;
if (pppoe_client_ptr -> nx_pppoe_host_uniq)
{
- /* Calculate the name length. */
- if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_host_uniq), &tag_length, NX_MAX_STRING_LENGTH))
- {
-
- /* Packet too small. */
- nx_packet_release(packet_ptr);
- return(NX_PPPOE_CLIENT_PACKET_PAYLOAD_ERROR);
- }
-
if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >=
- (4 + tag_length))
+ (4 + pppoe_client_ptr -> nx_pppoe_host_uniq_length))
{
/* Added the Host-Uniq tag. */
- _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, tag_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index);
+ _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, pppoe_client_ptr -> nx_pppoe_host_uniq_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index);
}
else
{
diff --git a/addons/pppoe/nx_pppoe_client.h b/addons/pppoe/nx_pppoe_client.h
index 8c03978e..64637e99 100644
--- a/addons/pppoe/nx_pppoe_client.h
+++ b/addons/pppoe/nx_pppoe_client.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nx_pppoe_client.h PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -44,6 +44,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* string length verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -228,7 +231,9 @@ typedef struct NX_PPPOE_CLIENT_STRUCT
UINT nx_pppoe_state;
NX_PPPOE_SERVER_SESSION nx_pppoe_server_session;
UCHAR *nx_pppoe_service_name;
+ UINT nx_pppoe_service_name_length;
UCHAR *nx_pppoe_host_uniq;
+ UINT nx_pppoe_host_uniq_length;
UCHAR nx_pppoe_ac_name[NX_PPPOE_CLIENT_MAX_AC_NAME_SIZE];
UINT nx_pppoe_ac_name_size;
UCHAR nx_pppoe_ac_cookie[NX_PPPOE_CLIENT_MAX_AC_COOKIE_SIZE];
diff --git a/addons/ptp/nxd_ptp_client.c b/addons/ptp/nxd_ptp_client.c
new file mode 100644
index 00000000..1be23884
--- /dev/null
+++ b/addons/ptp/nxd_ptp_client.c
@@ -0,0 +1,3736 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX PTP Client Component */
+/** */
+/** Precision Time Protocol (PTP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* APPLICATION INTERFACE DEFINITION RELEASE */
+/* */
+/* nxd_ptp_client.c PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the NetX Precision Time Protocol (PTP) */
+/* Client component, including all data types and external references. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+/* Force error checking to be disabled in this module */
+
+#ifndef NX_DISABLE_ERROR_CHECKING
+#define NX_DISABLE_ERROR_CHECKING
+#endif
+
+#define NX_PTP_SOURCE_CODE
+
+#include "nxd_ptp_client.h"
+#include "nx_udp.h"
+#include "nx_ipv4.h"
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+#include "nx_ipv6.h"
+#endif
+#include "tx_timer.h"
+
+/* #define NX_PTP_DEBUG */
+/* #define NX_PTP_DEBUG_OFFSET */
+#if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
+#include <stdio.h>
+#endif
+#ifdef NX_PTP_DEBUG
+#ifndef NX_PTP_DEBUG_PRINTF
+#define NX_PTP_DEBUG_PRINTF(x) printf x
+#endif
+#else
+#define NX_PTP_DEBUG_PRINTF(x)
+#endif
+
+/* Bring in externs for caller checking code. */
+
+NX_CALLER_CHECKING_EXTERNS
+
+/* number of nanoseconds per second */
+#define NX_PTP_NANOSECONDS_PER_SEC 1000000000L
+
+/* Define the PTP version */
+#define NX_PTP_VERSION 2
+
+/* Define the UDP ports */
+#define NX_PTP_EVENT_UDP_PORT 319
+#define NX_PTP_GENERAL_UDP_PORT 320
+
+/* Define the TTL of PTP packets */
+#define NX_PTP_TIME_TO_LIVE 1
+
+/* Define the IPv4 multicast address "224.0.1.129" */
+#define NX_PTP_IPV4_MULTICAST_ADDR IP_ADDRESS(224, 0, 1, 129)
+
+/* Define the IPv6 multicast address "ff0e::181" */
+#define NX_PTP_IPV6_MULTICAST_ADDR_SET(x) { \
+ (x) -> nxd_ip_version = NX_IP_VERSION_V6; \
+ (x) -> nxd_ip_address.v6[0] = 0xff0e0000UL; \
+ (x) -> nxd_ip_address.v6[1] = 0; \
+ (x) -> nxd_ip_address.v6[2] = 0; \
+ (x) -> nxd_ip_address.v6[3] = 0x181; }
+
+/* Length of PTP message header */
+#define NX_PTP_MSG_HDR_LEN 34
+
+/* Length of PTP messages (without header) */
+#define NX_PTP_MSG_ANNOUNCE_LEN 30
+#define NX_PTP_MSG_SYNC_LEN 10
+#define NX_PTP_MSG_FOLLOW_UP_LEN 10
+#define NX_PTP_MSG_DELAY_RESP_LEN 20
+
+/* Length of PTP timestamp */
+#define NX_PTP_MSG_TIMESTAMP_LEN 10
+
+/* Get version number */
+#define NX_PTP_MSG_VERSION(p_) ((p_)[1] & 0xf)
+
+/* Get domain number */
+#define NX_PTP_MSG_DOMAIN(p_) ((p_)[4])
+
+/* Type of messages */
+#define NX_PTP_MSG_TYPE_SYNC 0
+#define NX_PTP_MSG_TYPE_DELAY_REQ 1
+#define NX_PTP_MSG_TYPE_FOLLOW_UP 8
+#define NX_PTP_MSG_TYPE_DELAY_RESP 9
+#define NX_PTP_MSG_TYPE_ANNOUNCE 11
+
+/* Message flags */
+#define NX_PTP_MSG_HDR_FLAG_LEAP61 (1 << 0)
+#define NX_PTP_MSG_HDR_FLAG_LEAP59 (1 << 1)
+#define NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE (1 << 2)
+#define NX_PTP_MSG_HDR_FLAG_TWO_STEP (1 << 9)
+
+/* Common Message Header */
+typedef struct NX_PTP_MSG_HEADER_STRUCT
+{
+ UCHAR transportSpecific;
+ UCHAR messageType;
+ UCHAR versionPTP;
+ UCHAR domainNumber;
+ USHORT messageLength;
+ USHORT flagField;
+ ULONG cFieldHigh;
+ ULONG cFieldLow;
+ UCHAR *sourcePortIdentity;
+ USHORT sequenceId;
+ UCHAR logMessageInterval;
+} NX_PTP_MSG_HEADER;
+
+/* Get UTC offset from announce message */
+#define NX_PTP_MSG_UTC_OFFSET(p_) ((SHORT)((p_[10] << 8) | p_[11]))
+
+/* Macros for reading PTP packet fields */
+#define NX_PTP_RD16(p_, v_) { \
+ USHORT t_; \
+ t_ = *p_++; \
+ t_ = (USHORT)(t_ << 8); \
+ v_ = (USHORT)(t_ | *p_++); }
+
+#define NX_PTP_RD32(p_, v_) { \
+ ULONG t_; \
+ t_ = *p_++; \
+ t_ <<= 8; \
+ t_ |= *p_++; \
+ t_ <<= 8; \
+ t_ |= *p_++; \
+ t_ <<= 8; \
+ v_ = t_ |= *p_++; }
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_msg_parse_timestamp PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses timestamp field of a PTP message. */
+/* */
+/* INPUT */
+/* */
+/* ptr Pointer to PTP message */
+/* time_ptr Pointer to PTP time for output*/
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_sync_received Process Sync message */
+/* _nx_ptp_client_delay_resp_received Process delay response */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_msg_parse_timestamp(UCHAR *ptr, NX_PTP_TIME *time_ptr)
+{
+ULONG nanoseconds = (ULONG)time_ptr -> nanosecond;
+
+ NX_PTP_RD16(ptr, time_ptr -> second_high);
+ NX_PTP_RD32(ptr, time_ptr -> second_low);
+ NX_PTP_RD32(ptr, nanoseconds);
+ time_ptr -> nanosecond = (LONG)nanoseconds;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_msg_parse_hdr PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses the header of a PTP packet. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* packet_ptr Pointer to PTP packet */
+/* hdr Parsed PTP header for output */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nxd_udp_packet_info_extract Extract UDP packet information*/
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_process_event_packet Process PTP event packet */
+/* _nx_ptp_client_process_general_packet Process PTP general packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static UINT _nx_ptp_msg_parse_hdr(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_MSG_HEADER *hdr)
+{
+UCHAR b;
+UCHAR *ptr;
+UINT len;
+UINT status;
+NXD_ADDRESS src_addr;
+UINT interface_index;
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+ if (packet_ptr -> nx_packet_next)
+ {
+
+ /* Chained packet is not supported */
+ return(NX_NOT_SUPPORTED);
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
+ /* get pointer to PTP message */
+ ptr = packet_ptr -> nx_packet_prepend_ptr;
+
+ /* get length of PTP message */
+ len = packet_ptr -> nx_packet_length;
+
+ /* check packet validity: */
+ /* - length >= PTP header length */
+ /* - PTP version */
+ /* - domain number */
+ if ((len < NX_PTP_MSG_HDR_LEN) ||
+ (NX_PTP_MSG_VERSION(ptr) != NX_PTP_VERSION) ||
+ (NX_PTP_MSG_DOMAIN(ptr) != client_ptr -> nx_ptp_client_domain))
+ {
+
+ /* discard invalid packet */
+ return(NX_INVALID_PACKET);
+ }
+
+ /* get info about sender and check packet validity: */
+ /* - network interface */
+ /* - IP version */
+ status = nxd_udp_packet_info_extract(packet_ptr, &src_addr, NX_NULL, NX_NULL, &interface_index);
+ if ((status != NX_SUCCESS) ||
+ (interface_index != client_ptr -> nx_ptp_client_interface_index)
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+ || ((src_addr.nxd_ip_version == NX_IP_VERSION_V4) &&
+ !client_ptr -> nx_ptp_client_ipv4_group_joined) ||
+ ((src_addr.nxd_ip_version == NX_IP_VERSION_V6) &&
+ !client_ptr -> nx_ptp_client_ipv6_group_joined)
+#endif
+ )
+ {
+
+ /* discard invalid packet */
+ return(NX_INVALID_PACKET);
+ }
+
+ /* Save source address in listening state */
+ if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING)
+ {
+ client_ptr -> nx_ptp_client_master_addr = src_addr;
+ }
+
+ b = *ptr++;
+ hdr -> transportSpecific = b >> 4;
+ hdr -> messageType = b & 0xf;
+ b = *ptr++;
+ hdr -> versionPTP = b & 0xf;
+ NX_PTP_RD16(ptr, hdr -> messageLength);
+ hdr -> domainNumber = *ptr++;
+ ptr++; /* reserved */
+ NX_PTP_RD16(ptr, hdr -> flagField);
+ NX_PTP_RD32(ptr, hdr -> cFieldHigh);
+ NX_PTP_RD32(ptr, hdr -> cFieldLow);
+ ptr += 4; /* reserved */
+ hdr -> sourcePortIdentity = ptr;
+ ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
+ NX_PTP_RD16(ptr, hdr -> sequenceId);
+ ptr++; /* controlField - ignore */
+ hdr -> logMessageInterval = *ptr;
+
+ /* adjust message length */
+ if (len > hdr -> messageLength)
+ {
+ if (hdr -> messageLength < NX_PTP_MSG_HDR_LEN)
+ {
+
+ /* invalid length */
+ return(NX_INVALID_PACKET);
+ }
+ len = hdr -> messageLength;
+ }
+
+ /* Adjust packet. */
+ packet_ptr -> nx_packet_prepend_ptr += NX_PTP_MSG_HDR_LEN;
+ packet_ptr -> nx_packet_length = len - NX_PTP_MSG_HDR_LEN;
+
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_msg_parse_announce PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses PTP Announce message. */
+/* */
+/* INPUT */
+/* */
+/* ptr Pointer to PTP message */
+/* master_ptr Parsed PTP master for output */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_announce_received Process Announce message */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_msg_parse_announce(UCHAR *ptr, NX_PTP_CLIENT_MASTER *master)
+{
+ ptr += NX_PTP_MSG_TIMESTAMP_LEN + 2 + 1; /* originTimestamp, utcOffset, reserved */
+ master -> nx_ptp_client_master_priority1 = *ptr++;
+ master -> nx_ptp_client_master_clock_class = *ptr++;
+ master -> nx_ptp_client_master_clock_accuracy = *ptr++;
+ NX_PTP_RD16(ptr, master -> nx_ptp_client_master_offset_scaled_log_variance);
+ master -> nx_ptp_client_master_priority2 = *ptr++;
+ master -> nx_ptp_client_master_grandmaster_identity = ptr;
+ ptr += NX_PTP_CLOCK_IDENTITY_SIZE;
+ NX_PTP_RD16(ptr, master -> nx_ptp_client_master_steps_removed);
+ master -> nx_ptp_client_master_time_source = *ptr;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_soft_clock_adjust PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function adjusts the value of the soft PTP clock. */
+/* */
+/* INPUT */
+/* */
+/* ptp_instance Pointer to PTP client */
+/* offset_ns Signed number of nanoseconds */
+/* to add to the PTP clock */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
+/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_soft_clock_callback Soft PTP clock */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_soft_clock_adjust(VOID *ptp_instance, LONG offset_ns)
+{
+NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
+TX_INTERRUPT_SAVE_AREA
+
+ /* enforce min/max values of offset */
+ if (offset_ns > NX_PTP_NANOSECONDS_PER_SEC)
+ {
+ offset_ns = NX_PTP_NANOSECONDS_PER_SEC;
+ }
+ else if (offset_ns < -NX_PTP_NANOSECONDS_PER_SEC)
+ {
+ offset_ns = -NX_PTP_NANOSECONDS_PER_SEC;
+ }
+
+ /* add the number of nanosecond to the current time */
+ TX_DISABLE
+ client_ptr -> nx_ptp_client_soft_clock.nanosecond += offset_ns;
+ if (client_ptr -> nx_ptp_client_soft_clock.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
+ {
+ client_ptr -> nx_ptp_client_soft_clock.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_inc64(&client_ptr -> nx_ptp_client_soft_clock.second_high,
+ &client_ptr -> nx_ptp_client_soft_clock.second_low);
+ }
+ else if (client_ptr -> nx_ptp_client_soft_clock.nanosecond < 0)
+ {
+ client_ptr -> nx_ptp_client_soft_clock.nanosecond += NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_dec64(&client_ptr -> nx_ptp_client_soft_clock.second_high,
+ &client_ptr -> nx_ptp_client_soft_clock.second_low);
+ }
+ TX_RESTORE
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_timer_handler PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function implements the PTP client timer handler. */
+/* */
+/* INPUT */
+/* */
+/* ptp_instance Pointer to PTP client */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_event_flags_set Set PTP timer event */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Timer */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_timer_handler(ULONG ptp_instance)
+{
+NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
+
+ /* Update soft timer. */
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE,
+ &client_ptr -> nx_ptp_client_soft_clock, NX_NULL,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+
+ /* set timer event */
+ tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_TIMER_EVENT, TX_OR);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_socket_receive_notify PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is invoked when UDP packet is received. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to general socket */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_event_flags_set Set UDP receive event */
+/* */
+/* CALLED BY */
+/* */
+/* NetX UDP */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_socket_receive_notify(NX_UDP_SOCKET *socket_ptr)
+{
+NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)(socket_ptr -> nx_udp_socket_reserved_ptr);
+
+ /* set timer event */
+ tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_RX_EVENT, TX_OR);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_clock_adjust PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* Adjust the PTP clock with the given offset */
+/* If the offset is greater than one second, the clock is updated, */
+/* otherwise it is adjusted with the number of nanoseconds. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* offset_ptr Pointer to time offset */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
+/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */
+/* _nx_ptp_client_utility_add64 Add two 64-bit number */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_delay_resp_received Process delay response */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_clock_adjust(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *offset_ptr)
+{
+NX_PTP_TIME current;
+
+ if ((offset_ptr -> second_high == 0) && (offset_ptr -> second_low == 0))
+ {
+
+ /* offset less than 1s, adjust clock */
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_ADJUST, offset_ptr, NX_NULL,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+ NX_PTP_DEBUG_PRINTF(("PTP: adjust clock %d ns\r\n", (INT)offset_ptr -> nanosecond));
+ }
+ else
+ {
+
+ /* offset greater than 1s, set new clock value */
+ /* get current clock value */
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET, &current, NX_NULL,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+
+ /* add nanoseconds offset */
+ current.nanosecond += offset_ptr -> nanosecond;
+
+ /* ensure nanosecond field is in range 0-999999999 */
+ if (current.nanosecond < 0)
+ {
+ current.nanosecond += NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_dec64(&current.second_high, &current.second_low);
+ }
+ else if (current.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
+ {
+ current.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_inc64(&current.second_high, &current.second_low);
+ }
+
+ /* add seconds offset */
+ _nx_ptp_client_utility_add64(&current.second_high, &current.second_low,
+ offset_ptr -> second_high, offset_ptr -> second_low);
+
+ /* set new clock value */
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET, &current, NX_NULL,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+
+ NX_PTP_DEBUG_PRINTF(("PTP: set clock %u.%d\r\n",
+ (UINT)current.second_low,
+ (INT)current.nanosecond));
+ }
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_send_delay_req PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sends a PTP Delay Request message. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_allocate Allocate a packet */
+/* nxd_udp_socket_source_send Send a UDP packet */
+/* nx_packet_release Release a packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_sync_received Process Sync message */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_send_delay_req(NX_PTP_CLIENT *client_ptr)
+{
+NX_PACKET *packet_ptr;
+UINT status = NX_NOT_SUCCESSFUL;
+UCHAR *ptr;
+NXD_ADDRESS addr;
+UINT addr_index = 0;
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+NXD_IPV6_ADDRESS *ipv6_addr;
+NX_IP *ip_ptr;
+NX_INTERFACE *if_ptr;
+#endif
+
+ NX_PTP_DEBUG_PRINTF(("PTP: send DELAY_REQ\r\n"));
+
+ /* allocate a packet from the pool */
+ status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_NO_WAIT);
+ if (status != NX_SUCCESS)
+ {
+ /* Failed to allocate the packet */
+ return;
+ }
+
+ /* start of message */
+ ptr = packet_ptr -> nx_packet_prepend_ptr;
+
+#define PTP_MSG_DELAY_REQ_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN)
+#define PTP_MSG_DELAY_REQ_ZERO1_LEN (1 + 2 + 8 + 4)
+
+ /* write header */
+ *ptr++ = NX_PTP_MSG_TYPE_DELAY_REQ;
+ *ptr++ = NX_PTP_VERSION;
+ *ptr++ = PTP_MSG_DELAY_REQ_TOTAL_LEN >> 8;
+ *ptr++ = (UCHAR)PTP_MSG_DELAY_REQ_TOTAL_LEN;
+ *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | client_ptr -> nx_ptp_client_domain;
+ memset(ptr, 0, PTP_MSG_DELAY_REQ_ZERO1_LEN); /* reserved/flags/correction/reserved */
+ ptr += PTP_MSG_DELAY_REQ_ZERO1_LEN;
+ memcpy(ptr, client_ptr -> nx_ptp_client_port_identity,
+ NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
+ ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
+ client_ptr -> nx_ptp_client_delay_req_id++;
+ *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_delay_req_id >> 8);
+ *ptr++ = (UCHAR)client_ptr -> nx_ptp_client_delay_req_id;
+ *ptr++ = 0; /* control */
+ *ptr++ = 0; /* XXX */
+
+ /* write timestamp (0) */
+ memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN);
+ ptr += NX_PTP_MSG_TIMESTAMP_LEN;
+
+ /* set final length of message */
+ packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr);
+ packet_ptr -> nx_packet_append_ptr = ptr;
+
+ /* set source and destination addresses */
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+ if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr);
+
+ /* Use first IPv6 address as source address. */
+ ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
+ if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
+ ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
+ if (ipv6_addr == NX_NULL)
+ {
+
+ /* No available IPv6 address. */
+ /* Release packet. */
+ nx_packet_release(packet_ptr);
+
+ /* Reset state. */
+ client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
+ client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL;
+
+ return;
+ }
+ addr_index = ipv6_addr -> nxd_ipv6_address_index;
+ }
+ else
+#endif
+ {
+#ifndef NX_DISABLE_IPV4
+ addr.nxd_ip_version = NX_IP_VERSION_V4;
+ addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR;
+ addr_index = client_ptr -> nx_ptp_client_interface_index;
+#endif
+ }
+
+ /* Prepare timestamp for current packet */
+ client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_REQ_TS;
+ client_ptr -> nx_ptp_client_delay_req_packet_ptr = packet_ptr;
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE,
+ &client_ptr -> nx_ptp_client_delay_ts, packet_ptr,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+
+ /* Send delay request */
+ status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
+ packet_ptr, &addr, NX_PTP_EVENT_UDP_PORT, addr_index);
+ if (status)
+ {
+
+ /* release packet in case of error */
+ nx_packet_release(packet_ptr);
+
+ /* reset state */
+ client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
+ client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL;
+
+ return;
+ }
+
+ /* rearm delay req timer */
+ client_ptr -> nx_ptp_client_delay_req_timer = NX_PTP_CLIENT_DELAY_REQ_INTERVAL;
+ client_ptr -> nx_ptp_client_delay_req_flag = 0;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_sync_received PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes a received PTP Sync message. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* ts_ptr Pointer to the timestamp */
+/* delivered by the Sync message*/
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_msg_parse_timestamp Parse timestamp field */
+/* _nx_ptp_client_send_delay_req Send delay request */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_process_event_packet Process PTP event packet */
+/* _nx_ptp_client_process_general_packet Process PTP general packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_sync_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr)
+{
+ NX_PTP_DEBUG_PRINTF(("PTP: rcv SYNC\r\n"));
+
+ /* store Sync master timestamp */
+ _nx_ptp_msg_parse_timestamp(ts_ptr, &client_ptr -> nx_ptp_client_sync);
+
+ /* delay and offset determination */
+ if (client_ptr -> nx_ptp_client_delay_req_flag)
+ {
+
+ /* send delay request message */
+ /* (delay_req_flag is cleared by this function) */
+ _nx_ptp_client_send_delay_req(client_ptr);
+ }
+
+ /* update Sync state */
+ client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_delay_resp_received PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes a received PTP Delay Response message. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* ts_ptr Pointer to the timestamp */
+/* delivered by the Delay Resp */
+/* message */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_clock_adjust Adjust PTP clock */
+/* _nx_ptp_msg_parse_timestamp Parse timestamp field */
+/* _nx_ptp_client_utility_time_diff Diff two PTP times */
+/* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_process_general_packet Process PTP general packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_delay_resp_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr)
+{
+NX_PTP_TIME t4, a, b;
+NX_PTP_CLIENT_SYNC sync;
+
+ NX_PTP_DEBUG_PRINTF(("PTP: rcv DELAY_RESP\r\n"));
+
+ /*
+ * The following timestamps are used for delay/offset determination:
+ *
+ * t1 = nx_ptp_client_sync
+ * t2 = nx_ptp_client_sync_ts
+ * t3 = nx_ptp_client_delay_ts
+ * t4 = timestamp in Delay_Resp message (ts_ptr)
+ *
+ * A = t2 - t1
+ * B = t4 - t3
+ *
+ * delay = (A + B) / 2
+ * offset = (B - A) / 2
+ */
+
+ /* check for valid timestamp t1 */
+ if ((client_ptr -> nx_ptp_client_sync.second_low == 0) &&
+ (client_ptr -> nx_ptp_client_sync.second_high == 0))
+ {
+ return;
+ }
+
+ /* get master clock timestamp */
+ _nx_ptp_msg_parse_timestamp(ts_ptr, &t4);
+
+ /* compute A = t2 - t1 */
+ _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync_ts, &client_ptr -> nx_ptp_client_sync, &a);
+
+ /* compute B = t4 - t3 */
+ _nx_ptp_client_utility_time_diff(&t4, &client_ptr -> nx_ptp_client_delay_ts, &b);
+
+ /* compute offset = (B - A) / 2 */
+ _nx_ptp_client_utility_time_diff(&b, &a, &a);
+ _nx_ptp_client_utility_time_div_by_2(&a);
+
+#if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
+ if ((a.second_low == 0) && (a.second_high == 0))
+ {
+ if ((a.nanosecond > -1000) && (a.nanosecond < 1000))
+ {
+ printf("PTP: offset = %ld ns\n", a.nanosecond);
+ }
+ else if ((a.nanosecond > -1000000) && (a.nanosecond < 1000000))
+ {
+ printf("PTP: offset = %ld us\n", a.nanosecond / 1000);
+ }
+ else
+ {
+ printf("PTP: offset = %ld ms\n", a.nanosecond / 1000000);
+ }
+ }
+ else
+ {
+ printf("PTP: offset > 1s\n");
+ }
+#endif
+
+ /* add the time offset the client clock */
+ _nx_ptp_client_clock_adjust(client_ptr, &a);
+
+ /* set calibrated flag */
+ if (!(client_ptr -> nx_ptp_client_sync_flags) & NX_PTP_CLIENT_SYNC_CALIBRATED)
+ {
+
+ client_ptr -> nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_CALIBRATED;
+
+ /* application callback */
+ if (client_ptr -> nx_ptp_client_event_callback)
+ {
+ sync.nx_ptp_client_sync_flags = client_ptr -> nx_ptp_client_sync_flags;
+ sync.nx_ptp_client_sync_utc_offset = client_ptr -> nx_ptp_client_utc_offset;
+ client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync,
+ client_ptr -> nx_ptp_client_event_callback_data);
+ }
+ }
+
+ /* update delay req state */
+ client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_announce_received PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes a received PTP Announce message. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* hdr Pointer to PTP header */
+/* ptr Pointer to PTP message */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_msg_parse_announce Parse Announce message */
+/* memcpy Copy memory */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_process_general_packet Process PTP general packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_announce_received(NX_PTP_CLIENT *client_ptr,
+ NX_PTP_MSG_HEADER *hdr,
+ UCHAR *ptr)
+{
+NX_PTP_CLIENT_SYNC sync;
+NX_PTP_CLIENT_MASTER master;
+
+ /* parse Sync information */
+ sync.nx_ptp_client_sync_flags = 0;
+ if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE)
+ {
+ sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_UTC_REASONABLE;
+ }
+ if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP59)
+ {
+ sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP59;
+ }
+ if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP61)
+ {
+ sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP61;
+ }
+ sync.nx_ptp_client_sync_utc_offset = NX_PTP_MSG_UTC_OFFSET(ptr);
+
+ /* check for new master */
+ if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING)
+ {
+
+ /* first announce message, save master clock parameters */
+ client_ptr -> nx_ptp_client_sync_flags = sync.nx_ptp_client_sync_flags;
+ client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset;
+ memcpy(client_ptr -> nx_ptp_client_master_port_identity, hdr -> sourcePortIdentity,
+ NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
+
+ /* wait for Sync message */
+ client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC;
+ client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
+ client_ptr -> nx_ptp_client_delay_req_timer = -1;
+ client_ptr -> nx_ptp_client_delay_req_flag = 1;
+
+
+ /* call application callback */
+ if (client_ptr -> nx_ptp_client_event_callback)
+ {
+
+ /* parse annouce message */
+ _nx_ptp_msg_parse_announce(ptr, &master);
+ master.nx_ptp_client_master_address = &(client_ptr -> nx_ptp_client_master_addr);
+ master.nx_ptp_client_master_port_identity = hdr -> sourcePortIdentity;
+ client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER, &master,
+ client_ptr -> nx_ptp_client_event_callback_data);
+ }
+ }
+ else
+ {
+
+ /* check for UTC offset update or flags changes */
+ if (((client_ptr -> nx_ptp_client_sync_flags & ~NX_PTP_CLIENT_SYNC_CALIBRATED) !=
+ sync.nx_ptp_client_sync_flags) ||
+ (client_ptr -> nx_ptp_client_utc_offset != sync.nx_ptp_client_sync_utc_offset))
+ {
+ client_ptr -> nx_ptp_client_sync_flags =
+ (USHORT)((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) |
+ sync.nx_ptp_client_sync_flags);
+ client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset;
+
+ /* call application callback */
+ if ((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) &&
+ (client_ptr -> nx_ptp_client_event_callback))
+ {
+ client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync,
+ client_ptr -> nx_ptp_client_event_callback_data);
+ }
+ }
+ }
+
+ /* reset annouce timer */
+ client_ptr -> nx_ptp_client_announce_timeout = NX_PTP_CLIENT_ANNOUNCE_EXPIRATION;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_process_event_packet PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes PTP packet received through event socket. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* packet_ptr Pointer to PTP packet */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_sync_received Process Sync message */
+/* _nx_ptp_msg_parse_hdr Parse PTP header */
+/* memcmp Compare memory */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_thread_entry PTP thread entry */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_process_event_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr)
+{
+NX_PTP_MSG_HEADER hdr;
+
+ /* parse PTP message header */
+ if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr))
+ {
+ return;
+ }
+
+ /* check origin of message */
+ if (memcmp(&client_ptr -> nx_ptp_client_master_port_identity,
+ hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0)
+ {
+
+ /* not from our master clock */
+ return;
+ }
+
+ if (hdr.messageType != NX_PTP_MSG_TYPE_SYNC)
+ {
+ return;
+ }
+
+ if (((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_SYNC) &&
+ (client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP)) ||
+ (packet_ptr -> nx_packet_length < NX_PTP_MSG_SYNC_LEN))
+ {
+
+ /* not waiting for Sync or invalid message */
+ return;
+ }
+
+ /* retrieve timestamp of event message */
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT,
+ &client_ptr -> nx_ptp_client_sync_ts, packet_ptr,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+
+ /* two-step message? */
+ if (hdr.flagField & NX_PTP_MSG_HDR_FLAG_TWO_STEP)
+ {
+
+ /* wait for follow up message */
+ client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP;
+ client_ptr -> nx_ptp_client_sync_id = hdr.sequenceId;
+ }
+ else
+ {
+
+ /* process Sync event */
+ _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
+ }
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_process_general_packet PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes PTP packet received through general socket. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* packet_ptr Pointer to PTP packet */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_sync_received Process Sync message */
+/* _nx_ptp_msg_parse_hdr Parse PTP header */
+/* _nx_ptp_client_delay_resp_received Process delay response */
+/* _nx_ptp_client_announce_received Process Announce message */
+/* memcmp Compare memory */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_thread_entry PTP thread entry */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_process_general_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr)
+{
+NX_PTP_MSG_HEADER hdr;
+
+ /* parse PTP message header */
+ if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr))
+ {
+ return;
+ }
+
+ /* check origin of message */
+ if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_LISTENING) &&
+ (memcmp(&client_ptr -> nx_ptp_client_master_port_identity,
+ hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0))
+ {
+
+ /* not from our master clock */
+ return;
+ }
+
+ /* process ANNOUNCE message */
+ if (hdr.messageType == NX_PTP_MSG_TYPE_ANNOUNCE)
+ {
+ if (packet_ptr -> nx_packet_length < NX_PTP_MSG_ANNOUNCE_LEN)
+ {
+
+ /* invalid message */
+ return;
+ }
+
+ /* process announce message */
+ _nx_ptp_client_announce_received(client_ptr, &hdr, packet_ptr -> nx_packet_prepend_ptr);
+ }
+ else if (hdr.messageType == NX_PTP_MSG_TYPE_FOLLOW_UP)
+ {
+ if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP) ||
+ (client_ptr -> nx_ptp_client_sync_id != hdr.sequenceId) ||
+ (packet_ptr -> nx_packet_length < NX_PTP_MSG_FOLLOW_UP_LEN))
+ {
+
+ /* not a follow up for a previous Sync or invalid message */
+ return;
+ }
+
+ /* process Sync message */
+ _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
+ }
+ else if (hdr.messageType == NX_PTP_MSG_TYPE_DELAY_RESP)
+ {
+ if ((client_ptr -> nx_ptp_client_delay_state != NX_PTP_CLIENT_DELAY_WAIT_RESP) ||
+ (client_ptr -> nx_ptp_client_delay_req_id != hdr.sequenceId) ||
+ (packet_ptr -> nx_packet_length < NX_PTP_MSG_DELAY_RESP_LEN) ||
+ (memcmp(client_ptr -> nx_ptp_client_port_identity,
+ packet_ptr -> nx_packet_prepend_ptr + NX_PTP_MSG_TIMESTAMP_LEN,
+ NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0))
+ {
+
+ /* not a delay_resp for a previous delay_req or invalid message */
+ return;
+ }
+
+ /* process delay response message */
+ _nx_ptp_client_delay_resp_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
+ }
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_thread_entry PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function implements the PTP client processing thread. */
+/* */
+/* INPUT */
+/* */
+/* ptp_instance Pointer to PTP client */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_process_general_packet Process PTP general packet */
+/* _nx_ptp_client_process_event_packet Process PTP event packet */
+/* tx_event_flags_get Get PTP events */
+/* nx_udp_socket_receive Receive a UDP packet */
+/* nx_packet_release Release a packet */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+static VOID _nx_ptp_client_thread_entry(ULONG ptp_instance)
+{
+TX_INTERRUPT_SAVE_AREA
+NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
+ULONG ptp_events;
+UINT status;
+NX_PACKET *packet_ptr = NX_NULL;
+UCHAR packet_received;
+
+ /* start in listening state */
+ client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING;
+ client_ptr -> nx_ptp_client_delay_req_timer = -1;
+ client_ptr -> nx_ptp_client_announce_timeout = -1;
+
+ /* main loop */
+ for (;;)
+ {
+
+ /* wait for message */
+ status = tx_event_flags_get(&(client_ptr -> nx_ptp_client_events),
+ NX_PTP_CLIENT_ALL_EVENTS, TX_OR_CLEAR,
+ &ptp_events, TX_WAIT_FOREVER);
+ if (status != TX_SUCCESS)
+ {
+
+ /* error while reading queue, abort thread */
+ break;
+ }
+
+ if (ptp_events & NX_PTP_CLIENT_STOP_EVENT)
+ {
+
+ /* terminate thread */
+ break;
+ }
+
+ /*
+ * PTP Message Received
+ */
+ if (ptp_events & NX_PTP_CLIENT_RX_EVENT)
+ {
+
+ /* Loop to receive all packets. */
+ for (;;)
+ {
+ packet_received = NX_FALSE;
+ if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_general_socket),
+ &packet_ptr, NX_NO_WAIT) == NX_SUCCESS)
+ {
+ _nx_ptp_client_process_general_packet(client_ptr, packet_ptr);
+
+ /* Release packet. */
+ nx_packet_release(packet_ptr);
+ packet_received = NX_TRUE;
+ }
+
+ if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_event_socket),
+ &packet_ptr, NX_NO_WAIT) == NX_SUCCESS)
+ {
+ _nx_ptp_client_process_event_packet(client_ptr, packet_ptr);
+
+ /* Release packet. */
+ nx_packet_release(packet_ptr);
+ packet_received = NX_TRUE;
+ }
+
+ if (packet_received == NX_FALSE)
+ {
+
+ /* No more packets available. */
+ break;
+ }
+ }
+ }
+
+ /*
+ * Timer Event
+ */
+ if (ptp_events & NX_PTP_CLIENT_TIMER_EVENT)
+ {
+
+ /* announce messages timeout */
+ if ((client_ptr -> nx_ptp_client_announce_timeout > 0) &&
+ (--client_ptr -> nx_ptp_client_announce_timeout == 0))
+ {
+
+ /* no Annouce message received from master clock, back to listening state */
+ client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING;
+ client_ptr -> nx_ptp_client_delay_req_timer = -1;
+ client_ptr -> nx_ptp_client_announce_timeout = -1;
+
+ /* call handler */
+ if (client_ptr -> nx_ptp_client_event_callback)
+ {
+ client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_TIMEOUT, NX_NULL,
+ client_ptr -> nx_ptp_client_event_callback_data);
+ }
+ }
+
+ /* delay req interval timer */
+ if ((client_ptr -> nx_ptp_client_delay_req_timer > 0) &&
+ (--client_ptr -> nx_ptp_client_delay_req_timer == 0))
+ {
+
+ /* set flag */
+ client_ptr -> nx_ptp_client_delay_req_flag = 1;
+ }
+ }
+ }
+
+ /* set stopped state */
+ TX_DISABLE
+ client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPED;
+ TX_RESTORE
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_create PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP client create service. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* ip_ptr Pointer to client IP instance */
+/* interface_index Index of PTP network interface*/
+/* packet_pool_ptr Pointer to client packet pool */
+/* thread_priority Priority of PTP thread */
+/* thread_stack Pointer to thread stack */
+/* stack_size Size of thread stack */
+/* clock_callback PTP clock callback */
+/* clock_callback_data Data for the clock callback */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_create Actual create service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
+ NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
+ NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data)
+{
+
+ /* Check input parameters. */
+ if ((client_ptr == NX_NULL) || (ip_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) ||
+ (thread_stack == NX_NULL) || (stack_size == 0) || (clock_callback == NX_NULL))
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for invalid network interface input. */
+ if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
+ {
+ return(NX_INVALID_INTERFACE);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return _nx_ptp_client_create(client_ptr, ip_ptr, interface_index, packet_pool_ptr, thread_priority,
+ thread_stack, stack_size, clock_callback, clock_callback_data);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_create PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates the PTP client. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* ip_ptr Pointer to client IP instance */
+/* interface_index Index of PTP network interface*/
+/* packet_pool_ptr Pointer to client packet pool */
+/* thread_priority Priority of PTP thread */
+/* thread_stack Pointer to thread stack */
+/* stack_size Size of thread stack */
+/* clock_callback PTP clock callback */
+/* clock_callback_data Data for the clock callback */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* memset Reset memory */
+/* [clock_callback] Initialize clock */
+/* tx_event_flags_create Create PTP event flags */
+/* tx_event_flags_delete Delete PTP event flags */
+/* nx_udp_socket_create Create a UDP socket */
+/* nx_udp_socket_delete Delete a UDP socket */
+/* nx_udp_socket_receive_notify Set UDP receive notify */
+/* tx_timer_create Create a timer */
+/* tx_timer_delete Delete a timer */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
+ NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
+ NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data)
+{
+UINT status;
+
+ /* Null the members of NX_PTP_CLIENT. */
+ memset(client_ptr, 0, sizeof(NX_PTP_CLIENT));
+
+ /* Set the Client ID to indicate the PTP client thread is ready. */
+ client_ptr -> nx_ptp_client_id = NX_PTP_CLIENT_ID;
+
+ /* Set the IP instance. */
+ client_ptr -> nx_ptp_client_ip_ptr = ip_ptr;
+
+ /* Set the PTP network interface. */
+ client_ptr -> nx_ptp_client_interface_index = interface_index;
+
+ /* Set the packet pool, check for minimal packet size requirement. */
+ if (packet_pool_ptr -> nx_packet_pool_payload_size <
+ (NX_UDP_PACKET + NX_PTP_CLIENT_PACKET_DATA_SIZE))
+ {
+ return(NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD);
+ }
+ client_ptr -> nx_ptp_client_packet_pool_ptr = packet_pool_ptr;
+
+ /* Initialize callback function. */
+ status = clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_INIT, NX_NULL, NX_NULL, clock_callback_data);
+ if (status)
+ {
+
+ /* Fail to initialize clock in callback function. */
+ return(NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE);
+ }
+
+ /* Set the PTP clock callback */
+ client_ptr -> nx_ptp_client_clock_callback = clock_callback;
+ client_ptr -> nx_ptp_client_clock_callback_data = clock_callback_data;
+
+ /* create the internal PTP event flag object. */
+ status = tx_event_flags_create(&(client_ptr -> nx_ptp_client_events), "NetX PTP event flag");
+ if (status != TX_SUCCESS)
+ {
+ return(status);
+ }
+
+ /* create the general socket */
+ status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_general_socket,
+ "NetX PTP Client general socket", NX_IP_NORMAL,
+ NX_DONT_FRAGMENT, NX_PTP_TIME_TO_LIVE,
+ NX_PTP_CLIENT_MAX_QUEUE_DEPTH);
+ if (status != NX_SUCCESS)
+ {
+ tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
+ return(status);
+ }
+ client_ptr -> nx_ptp_client_general_socket.nx_udp_socket_reserved_ptr = client_ptr;
+ nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_general_socket, _nx_ptp_client_socket_receive_notify);
+
+ /* create the event socket */
+ status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_event_socket,
+ "NetX PTP Client event socket", NX_IP_NORMAL, NX_DONT_FRAGMENT,
+ NX_PTP_TIME_TO_LIVE,
+ NX_PTP_CLIENT_MAX_QUEUE_DEPTH);
+ if (status != NX_SUCCESS)
+ {
+ nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
+ tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
+ return(status);
+ }
+ client_ptr -> nx_ptp_client_event_socket.nx_udp_socket_reserved_ptr = client_ptr;
+ nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_event_socket, _nx_ptp_client_socket_receive_notify);
+
+ /* create the timer */
+ status = tx_timer_create(&client_ptr -> nx_ptp_client_timer,
+ "NetX PTP Client timer",
+ _nx_ptp_client_timer_handler,
+ (ULONG)client_ptr,
+ TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND,
+ TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND,
+ TX_NO_ACTIVATE);
+ if (status != TX_SUCCESS)
+ {
+ nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
+ nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket);
+ tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
+ return(status);
+ }
+
+ /* create the Client thread */
+ status = tx_thread_create(&client_ptr -> nx_ptp_client_thread,
+ "NetX PTP Client", _nx_ptp_client_thread_entry,
+ (ULONG)client_ptr, thread_stack, stack_size,
+ thread_priority, thread_priority,
+ NX_PTP_CLIENT_THREAD_TIME_SLICE, TX_DONT_START);
+ if (status != TX_SUCCESS)
+ {
+ nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
+ nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket);
+ tx_timer_delete(&client_ptr -> nx_ptp_client_timer);
+ tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
+ return(status);
+ }
+
+ /* return Success */
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_delete PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP client delete service. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_delete Actual delete service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr)
+{
+
+ /* Check input parameters. */
+ if (client_ptr == NX_NULL)
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return(_nx_ptp_client_delete(client_ptr));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_delete PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes the PTP client. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_stop Stop PTP service */
+/* tx_thread_suspend Suspend PTP thread */
+/* tx_thread_terminate Terminate PTP thread */
+/* tx_thread_delete Delete PTP thread */
+/* tx_event_flags_delete Delete PTP event flags */
+/* nx_udp_socket_delete Delete a UDP socket */
+/* tx_timer_delete Delete a timer */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr)
+{
+
+ /* Ensure the Client is stopped */
+ _nx_ptp_client_stop(client_ptr);
+
+ /* Suspend the Client thread. */
+ tx_thread_suspend(&client_ptr -> nx_ptp_client_thread);
+
+ /* Terminate Client thread. */
+ tx_thread_terminate(&client_ptr -> nx_ptp_client_thread);
+
+ /* Delete Client thread. */
+ tx_thread_delete(&client_ptr -> nx_ptp_client_thread);
+
+ /* Delete the timer */
+ tx_timer_delete(&client_ptr -> nx_ptp_client_timer);
+
+ /* Delete the general socket */
+ nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket);
+
+ /* Delete the event socket */
+ nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket);
+
+ /* Delete the event flag */
+ tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
+
+ /* return Success */
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_start PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP client start service. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* client_port_identity_ptr Pointer to client port and */
+/* identity */
+/* client_port_identity_length Length of client port and */
+/* identity */
+/* domain PTP clock domain */
+/* transport_specific Transport specific */
+/* event_callback Event callback */
+/* event_callback_data Data for the event callback */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_start Actual start service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
+ UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
+ VOID *event_callback_data)
+{
+
+ /* Check input parameters. */
+ if ((client_ptr == NX_NULL) ||
+ ((client_port_identity_ptr == NX_NULL) && (client_port_identity_length != 0)) ||
+ ((client_port_identity_ptr != NX_NULL) && (client_port_identity_length != NX_PTP_CLOCK_PORT_IDENTITY_SIZE)))
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return(_nx_ptp_client_start(client_ptr, client_port_identity_ptr, client_port_identity_length,
+ domain, transport_specific, event_callback, event_callback_data));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_start PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function starts the PTP client. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* client_port_identity_ptr Pointer to client port and */
+/* identity */
+/* client_port_identity_length Length of client port and */
+/* identity */
+/* domain PTP clock domain */
+/* transport_specific Transport specific */
+/* event_callback Event callback */
+/* event_callback_data Data for the event callback */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_thread_suspend Suspend PTP thread */
+/* tx_thread_terminate Terminate PTP thread */
+/* tx_thread_reset Reset PTP thread */
+/* tx_thread_resume Resume PTP thread */
+/* memcpy Copy memory */
+/* nx_ip_interface_physical_address_get Get physical address */
+/* nx_udp_socket_bind Bind UDP port */
+/* nx_ipv4_multicast_interface_join Join IPv4 multicast group */
+/* nxd_ipv6_multicast_interface_join Join IPv6 multicast group */
+/* tx_timer_activate Activate timer */
+/* _nx_ptp_client_stop Stop PTP service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
+ UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
+ VOID *event_callback_data)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT state;
+UINT status;
+ULONG msw, lsw;
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+NXD_ADDRESS maddr;
+#endif
+
+ NX_PARAMETER_NOT_USED(client_port_identity_length);
+
+ /* Check if Client is running */
+ TX_DISABLE
+ state = client_ptr -> nx_ptp_client_thread_state;
+ if (state == NX_PTP_CLIENT_THREAD_IDLE)
+ {
+ client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_RUNNING;
+ }
+ TX_RESTORE
+ if (state != NX_PTP_CLIENT_THREAD_IDLE)
+ {
+
+ /* Client is already running */
+ return(NX_PTP_CLIENT_ALREADY_STARTED);
+ }
+
+ /* ensure the thread is terminated */
+ tx_thread_suspend(&client_ptr -> nx_ptp_client_thread);
+ tx_thread_terminate(&client_ptr -> nx_ptp_client_thread);
+
+ /* save the client parameters */
+ client_ptr -> nx_ptp_client_domain = (UCHAR)domain;
+ client_ptr -> nx_ptp_client_transport_specific = (UCHAR)transport_specific;
+ client_ptr -> nx_ptp_client_event_callback = event_callback;
+ client_ptr -> nx_ptp_client_event_callback_data = event_callback_data;
+
+ /* reset and resume the thread */
+ status = tx_thread_reset(&client_ptr -> nx_ptp_client_thread);
+ if (status != TX_SUCCESS)
+ {
+ TX_DISABLE
+ client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE;
+ TX_RESTORE
+
+ return(status);
+ }
+ tx_thread_resume(&client_ptr -> nx_ptp_client_thread);
+
+ /* set the client port and identity */
+ if (client_port_identity_ptr != NX_NULL)
+ {
+
+ /* copy provided identifier */
+ memcpy(client_ptr -> nx_ptp_client_port_identity, client_port_identity_ptr,
+ NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
+ }
+ else
+ {
+
+ /* get MAC address of interface */
+ status = nx_ip_interface_physical_address_get(client_ptr -> nx_ptp_client_ip_ptr,
+ client_ptr -> nx_ptp_client_interface_index,
+ &msw, &lsw);
+ if (status == TX_SUCCESS)
+ {
+ /* convert 48-bit MAC address to 64-bit EUI */
+ client_ptr -> nx_ptp_client_port_identity[0] = (UCHAR)(msw >> 8);
+ client_ptr -> nx_ptp_client_port_identity[1] = (UCHAR)msw;
+ client_ptr -> nx_ptp_client_port_identity[2] = (UCHAR)(lsw >> 24);
+ client_ptr -> nx_ptp_client_port_identity[3] = 0xff;
+ client_ptr -> nx_ptp_client_port_identity[4] = 0xfe;
+ client_ptr -> nx_ptp_client_port_identity[5] = (UCHAR)(lsw >> 16);
+ client_ptr -> nx_ptp_client_port_identity[6] = (UCHAR)(lsw >> 8);
+ client_ptr -> nx_ptp_client_port_identity[7] = (UCHAR)lsw;
+
+ /* set default port number (1) */
+ client_ptr -> nx_ptp_client_port_identity[8] = 0;
+ client_ptr -> nx_ptp_client_port_identity[9] = 1;
+ }
+ }
+
+ /* bind the general socket */
+ if (status == TX_SUCCESS)
+ {
+ status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket,
+ NX_PTP_GENERAL_UDP_PORT, NX_NO_WAIT);
+ }
+
+ /* bind the event socket */
+ if (status == TX_SUCCESS)
+ {
+ status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
+ NX_PTP_EVENT_UDP_PORT, NX_NO_WAIT);
+ }
+
+ /* join the multicast groups */
+ if (status == TX_SUCCESS)
+ {
+ status = nx_ipv4_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
+ NX_PTP_IPV4_MULTICAST_ADDR,
+ client_ptr -> nx_ptp_client_interface_index);
+ if (status == TX_SUCCESS)
+ {
+ client_ptr -> nx_ptp_client_ipv4_group_joined = NX_TRUE;
+ }
+ }
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+ if (status == TX_SUCCESS)
+ {
+ NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr);
+ status = nxd_ipv6_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
+ &maddr, client_ptr -> nx_ptp_client_interface_index);
+ if (status == TX_SUCCESS)
+ {
+ client_ptr -> nx_ptp_client_ipv6_group_joined = NX_TRUE;
+ }
+ else if ((status == NX_NOT_SUPPORTED) && (client_ptr -> nx_ptp_client_ipv4_group_joined))
+ {
+
+ /* IPv6 not enabled, use IPv4 only */
+ status = TX_SUCCESS;
+ }
+ }
+#endif
+
+ /* activate the Client timer */
+ if (status == TX_SUCCESS)
+ {
+
+ /* activate the timer */
+ status = tx_timer_activate(&client_ptr -> nx_ptp_client_timer);
+ }
+
+ /* stop the client thread in case of error */
+ if (status != TX_SUCCESS)
+ {
+ _nx_ptp_client_stop(client_ptr);
+
+ /* return failure */
+ return(status);
+ }
+
+ /* return Success */
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_stop PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP client stop service. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_stop Actual stop service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr)
+{
+
+ /* Check input parameters. */
+ if (client_ptr == NX_NULL)
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return(_nx_ptp_client_stop(client_ptr));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_stop PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function stops the PTP client. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_timer_deactivate Deactivate timer */
+/* nx_udp_socket_unbind Unbind UDP port */
+/* nx_ipv4_multicast_interface_leave Leave IPv4 multicast group */
+/* nxd_ipv6_multicast_interface_leave Leave IPv6 multicast group */
+/* tx_event_flags_set Set PTP timer event */
+/* tx_thread_sleep Thread sleep */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT state;
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+NXD_ADDRESS maddr;
+#endif
+
+ /* Check if Client is running */
+ TX_DISABLE
+ state = client_ptr -> nx_ptp_client_thread_state;
+ if (state == NX_PTP_CLIENT_THREAD_RUNNING)
+ {
+ client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPING;
+ }
+ TX_RESTORE
+ if ((state != NX_PTP_CLIENT_THREAD_RUNNING) &&
+ (state != NX_PTP_CLIENT_THREAD_STOPPED))
+ {
+
+ /* Client is not running */
+ return(NX_PTP_CLIENT_NOT_STARTED);
+ }
+
+ /* deactivate the timer */
+ tx_timer_deactivate(&client_ptr -> nx_ptp_client_timer);
+
+ /* unbind the sockets */
+ nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket);
+ nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket);
+
+ /* leave multicast groups */
+ if (client_ptr -> nx_ptp_client_ipv4_group_joined)
+ {
+ nx_ipv4_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
+ NX_PTP_IPV4_MULTICAST_ADDR,
+ client_ptr -> nx_ptp_client_interface_index);
+ client_ptr -> nx_ptp_client_ipv4_group_joined = NX_FALSE;
+ }
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+ if (client_ptr -> nx_ptp_client_ipv6_group_joined)
+ {
+ NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr);
+ nxd_ipv6_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
+ &maddr, client_ptr -> nx_ptp_client_interface_index);
+ client_ptr -> nx_ptp_client_ipv6_group_joined = NX_FALSE;
+ }
+#endif
+
+ /* send STOP message */
+ tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_STOP_EVENT, TX_OR);
+
+ /* wait for thread termination */
+ while (state != NX_PTP_CLIENT_THREAD_STOPPED)
+ {
+ tx_thread_sleep(1);
+ TX_DISABLE
+ state = client_ptr -> nx_ptp_client_thread_state;
+ TX_RESTORE
+ }
+
+ /* set Idle state */
+ TX_DISABLE
+ client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE;
+ TX_RESTORE
+
+ /* return Success */
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_time_get PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP time get service. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* time_ptr Pointer to PTP time */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_time_get Actual time get service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
+{
+
+ /* Check input parameters. */
+ if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL))
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return(_nx_ptp_client_time_get(client_ptr, time_ptr));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_time_get PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets the current value of the PTP clock. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* time_ptr Pointer to PTP time */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
+{
+
+ /* Get the current PTP clock */
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET,
+ time_ptr, NX_NULL,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+
+ /* return Success */
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_time_set PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP time set service. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* time_ptr Pointer to PTP time */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_time_set Actual time set service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
+{
+
+ /* Check input parameters. */
+ if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL))
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return(_nx_ptp_client_time_set(client_ptr, time_ptr));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_time_set PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets the initial time of the PTP clock. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* time_ptr Pointer to PTP time */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT state;
+
+ /* Check if Client is running */
+ TX_DISABLE
+ state = client_ptr -> nx_ptp_client_thread_state;
+ TX_RESTORE
+
+ if (state != NX_PTP_CLIENT_THREAD_IDLE)
+ {
+
+ /* Cannot set the clock when the client is running */
+ return(NX_PTP_CLIENT_ALREADY_STARTED);
+ }
+
+ /* Set the current PTP clock */
+ client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET,
+ time_ptr, NX_NULL,
+ client_ptr -> nx_ptp_client_clock_callback_data);
+
+ /* return Success */
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_master_info_get PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP master info get service. */
+/* */
+/* INPUT */
+/* */
+/* master_ptr Pointer to PTP master clock */
+/* address Address of master clock */
+/* port_identity PTP master port and identity */
+/* port_identity_length Length of PTP master port and */
+/* identity */
+/* priority1 Priority1 of PTP master clock */
+/* priority2 Priority2 of PTP master clock */
+/* clock_class Class of PTP master clock */
+/* clock_accuracy Accuracy of PTP master clock */
+/* clock_variance Variance of PTP master clock */
+/* grandmaster_identity Identity of grandmaster clock */
+/* grandmaster_identity_length Length of grandmaster Identity*/
+/* steps_removed Steps removed from PTP header */
+/* time_source The source of timer used by */
+/* grandmaster clock */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_master_info_get Actual master info get service*/
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
+ UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
+ UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
+ UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source)
+{
+ if (master_ptr == NX_NULL)
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ return(_nx_ptp_client_master_info_get(master_ptr, address, port_identity, port_identity_length, priority1,
+ priority2, clock_class, clock_accuracy, clock_variance, grandmaster_identity,
+ grandmaster_identity_length, steps_removed, time_source));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_master_info_get PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets information of master clock. */
+/* */
+/* INPUT */
+/* */
+/* master_ptr Pointer to PTP master clock */
+/* address Address of master clock */
+/* port_identity PTP master port and identity */
+/* port_identity_length Length of PTP master port and */
+/* identity */
+/* priority1 Priority1 of PTP master clock */
+/* priority2 Priority2 of PTP master clock */
+/* clock_class Class of PTP master clock */
+/* clock_accuracy Accuracy of PTP master clock */
+/* clock_variance Variance of PTP master clock */
+/* grandmaster_identity Identity of grandmaster clock */
+/* grandmaster_identity_length Length of grandmaster Identity*/
+/* steps_removed Steps removed from PTP header */
+/* time_source The source of timer used by */
+/* grandmaster clock */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
+ UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
+ UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
+ UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source)
+{
+
+ /* Set master information when the output pointer is provided. */
+ if (address)
+ {
+ *address = *(master_ptr -> nx_ptp_client_master_address);
+ }
+
+ if (port_identity && port_identity_length)
+ {
+ *port_identity = master_ptr -> nx_ptp_client_master_port_identity;
+ *port_identity_length = NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
+ }
+
+ if (priority1)
+ {
+ *priority1 = master_ptr -> nx_ptp_client_master_priority1;
+ }
+
+ if (priority2)
+ {
+ *priority2 = master_ptr -> nx_ptp_client_master_priority2;
+ }
+
+ if (clock_class)
+ {
+ *clock_class = master_ptr -> nx_ptp_client_master_clock_class;
+ }
+
+ if (clock_accuracy)
+ {
+ *clock_accuracy = master_ptr -> nx_ptp_client_master_clock_accuracy;
+ }
+
+ if (clock_variance)
+ {
+ *clock_variance = master_ptr -> nx_ptp_client_master_offset_scaled_log_variance;
+ }
+
+ if (grandmaster_identity && grandmaster_identity_length)
+ {
+ *grandmaster_identity = master_ptr -> nx_ptp_client_master_grandmaster_identity;
+ *grandmaster_identity_length = NX_PTP_CLOCK_IDENTITY_SIZE;
+ }
+
+ if (steps_removed)
+ {
+ *steps_removed = master_ptr -> nx_ptp_client_master_steps_removed;
+ }
+
+ if (time_source)
+ {
+ *time_source = master_ptr -> nx_ptp_client_master_time_source;
+ }
+
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_sync_info_get PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP Sync get service. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* flags Flags in Sync message */
+/* utc_offset Offset between TAI and UTC */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_sync_info_get Actual Sync info get service */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset)
+{
+ if (sync_ptr == NX_NULL)
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ return(_nx_ptp_client_sync_info_get(sync_ptr, flags, utc_offset));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_sync_info_get PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets information of Sync message. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* flags Flags in Sync message */
+/* utc_offset Offset between TAI and UTC */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset)
+{
+
+ /* Set SYNC information when the output pointer is provided. */
+ if (flags)
+ {
+ *flags = sync_ptr -> nx_ptp_client_sync_flags;
+ }
+
+ if (utc_offset)
+ {
+ *utc_offset = sync_ptr -> nx_ptp_client_sync_utc_offset;
+ }
+
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_packet_timestamp_notify PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function notifies the PTP packet is transmitted with timestamp.*/
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* packet_ptr Pointer to PTP packet */
+/* timestamp_ptr Pointer to timestamp */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr)
+{
+
+ /* get timestamp of previous delay_req message */
+ if (client_ptr &&
+ (client_ptr -> nx_ptp_client_delay_state == NX_PTP_CLIENT_DELAY_WAIT_REQ_TS) &&
+ (client_ptr -> nx_ptp_client_delay_req_packet_ptr == packet_ptr))
+ {
+
+ /* store timestamp */
+ client_ptr -> nx_ptp_client_delay_ts = *timestamp_ptr;
+
+ /* update state */
+ client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_RESP;
+ }
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_soft_clock_callback PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function implements soft PTP clock. */
+/* */
+/* INPUT */
+/* */
+/* client_ptr Pointer to PTP client */
+/* operation PTP clock operation */
+/* time_ptr Pointer to timestamp */
+/* packet_ptr Pointer to PTP packet */
+/* callback_data Pointer to callback data */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */
+/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
+/* */
+/* CALLED BY */
+/* */
+/* PTP internal */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation,
+ NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr,
+ VOID *callback_data)
+{
+TX_INTERRUPT_SAVE_AREA
+
+ NX_PARAMETER_NOT_USED(callback_data);
+
+ switch (operation)
+ {
+
+ /* Nothing to do for soft initialization. */
+ case NX_PTP_CLIENT_CLOCK_INIT:
+ break;
+
+ /* Set clock. */
+ case NX_PTP_CLIENT_CLOCK_SET:
+ TX_DISABLE
+ client_ptr -> nx_ptp_client_soft_clock = *time_ptr;
+ TX_RESTORE
+ break;
+
+ /* Extract timestamp from packet.
+ For soft implementation, simply fallthrough and return current timestamp. */
+ case NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT:
+
+ /* Get clock. */
+ case NX_PTP_CLIENT_CLOCK_GET:
+ TX_DISABLE
+ *time_ptr = client_ptr -> nx_ptp_client_soft_clock;
+ TX_RESTORE
+ break;
+
+ /* Adjust clock. */
+ case NX_PTP_CLIENT_CLOCK_ADJUST:
+ _nx_ptp_client_soft_clock_adjust(client_ptr, time_ptr -> nanosecond);
+ break;
+
+ /* Prepare timestamp for current packet.
+ For soft implementation, simply notify current timestamp. */
+ case NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE:
+ _nx_ptp_client_packet_timestamp_notify(client_ptr, packet_ptr, &(client_ptr -> nx_ptp_client_soft_clock));
+ break;
+
+ /* Update soft timer. */
+ case NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE:
+ TX_DISABLE
+
+ /* increment the nanosecond field of the software clock */
+ time_ptr -> nanosecond +=
+ (LONG)(NX_PTP_NANOSECONDS_PER_SEC / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND);
+
+ /* update the second field */
+ if (time_ptr -> nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
+ {
+ time_ptr -> nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_inc64(&(time_ptr -> second_high),
+ &(time_ptr -> second_low));
+ }
+ TX_RESTORE
+ break;
+
+ default:
+ return(NX_PTP_PARAM_ERROR);
+ }
+
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_utility_time_diff PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP time difference service. */
+/* */
+/* INPUT */
+/* */
+/* time1_ptr Pointer to first PTP time */
+/* time2_ptr Pointer to second PTP time */
+/* result_ptr Pointer to result time1-time2 */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_utility_time_diff Actual time difference service*/
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
+{
+
+ /* Check input parameters. */
+ if ((time1_ptr == NX_NULL) || (time2_ptr == NX_NULL) || (result_ptr == NX_NULL))
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return(_nx_ptp_client_utility_time_diff(time1_ptr, time2_ptr, result_ptr));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_time_diff PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function computes the difference between two PTP times. */
+/* */
+/* INPUT */
+/* */
+/* time1_ptr Pointer to first PTP time */
+/* time2_ptr Pointer to second PTP time */
+/* result_ptr Pointer to result time1-time2 */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_utility_sub64 Subtracts two 64-bit numbers */
+/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */
+/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* _nx_ptp_client_delay_resp_received Process delay response */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
+{
+LONG sec_hi;
+ULONG sec_lo;
+LONG ns;
+
+ /* compute difference of seconds */
+ sec_hi = time1_ptr -> second_high;
+ sec_lo = time1_ptr -> second_low;
+ _nx_ptp_client_utility_sub64(&sec_hi, &sec_lo, time2_ptr -> second_high,
+ time2_ptr -> second_low);
+
+ /* compute difference of nanoseconds */
+ /* note: this cannot overflow as nanosecond field is in range +/-0-999999999 */
+ ns = time1_ptr -> nanosecond - time2_ptr -> nanosecond;
+
+ /* keep nanoseconds in range +/-0-999999999 */
+ if (ns <= -NX_PTP_NANOSECONDS_PER_SEC)
+ {
+ ns += NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
+ }
+ else if (ns >= NX_PTP_NANOSECONDS_PER_SEC)
+ {
+ ns -= NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
+ }
+
+ /* ensure the nanoseconds field has same sign as seconds field */
+ if ((sec_hi >= 0) && ((sec_hi != 0) || (sec_lo != 0)))
+ {
+ /* positive number of seconds */
+ if (ns < 0)
+ {
+ ns += NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
+ }
+ }
+ else if (sec_hi < 0)
+ {
+ /* negative number of seconds */
+ if (ns > 0)
+ {
+ ns -= NX_PTP_NANOSECONDS_PER_SEC;
+ _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
+ }
+ }
+
+ /* return result time */
+ result_ptr -> second_high = sec_hi;
+ result_ptr -> second_low = sec_lo;
+ result_ptr -> nanosecond = ns;
+
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_ptp_client_utility_convert_time_to_date PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors on the PTP time conversion service. */
+/* */
+/* INPUT */
+/* */
+/* time_ptr Pointer to PTP time */
+/* offset signed second offset to add */
+/* the PTP time */
+/* date_time_ptr Pointer to resulting date */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_utility_convert_time_to_date */
+/* Actual time conversion service*/
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr)
+{
+
+ /* Check input parameters. */
+ if ((time_ptr == NX_NULL) || (date_time_ptr == NX_NULL))
+ {
+
+ /* Return error status. */
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call the actual function. */
+ return(_nx_ptp_client_utility_convert_time_to_date(time_ptr, offset, date_time_ptr));
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_convert_time_to_date PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function converts a PTP time to a UTC date and time. */
+/* */
+/* INPUT */
+/* */
+/* time_ptr Pointer to PTP time */
+/* offset Signed second offset to add */
+/* the PTP time */
+/* date_time_ptr Pointer to resulting date */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_utility_add64 Add two 64-bit number */
+/* */
+/* CALLED BY */
+/* */
+/* Application */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr)
+{
+#define IS_LEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define SECS_PER_MINUTE 60
+#define SECS_PER_HOUR (60 * SECS_PER_MINUTE)
+#define SECS_PER_DAY (24 * SECS_PER_HOUR)
+LONG secs_high;
+ULONG secs_low;
+UINT year, month, day, hour, minute;
+ULONG secs_per_year, secs_per_month;
+ULONG weekday;
+UINT is_leap;
+
+ /* get number of seconds */
+ secs_high = time_ptr -> second_high;
+ secs_low = time_ptr -> second_low;
+
+ /* add local time offset */
+ if (offset != 0)
+ {
+ _nx_ptp_client_utility_add64(&secs_high, &secs_low, offset < 0 ? -1 : 0, (ULONG)offset);
+ }
+ if (secs_high < 0)
+ {
+
+ /* invalid negative time */
+ return(NX_PTP_PARAM_ERROR);
+ }
+
+ /* determine the current year from Epoch (January 1, 1970) */
+ year = 1970;
+ secs_per_year = 365 * SECS_PER_DAY;
+ is_leap = 0;
+ weekday = 4; /* thursday */
+ while ((secs_high > 0) || (secs_low >= secs_per_year))
+ {
+ if (secs_low < secs_per_year)
+ {
+ secs_high--;
+ }
+ secs_low -= secs_per_year;
+ weekday += is_leap ? 366 : 365;
+ year++;
+ is_leap = IS_LEAP(year) ? 1 : 0;
+ secs_per_year = is_leap ? 366 * SECS_PER_DAY : 365 * SECS_PER_DAY;
+ }
+ /* compute day of the week from remaining seconds */
+ weekday = (weekday + secs_low / SECS_PER_DAY) % 7;
+
+ /* determine current month */
+ month = 1;
+ secs_per_month = 31 * SECS_PER_DAY;
+ while (secs_low >= secs_per_month)
+ {
+ secs_low -= secs_per_month;
+ month++;
+ if (month == 2)
+ {
+
+ /* february */
+ secs_per_month = is_leap ? 29 * SECS_PER_DAY : 28 * SECS_PER_DAY;
+ }
+ else if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
+ {
+
+ /* april, june, september, november */
+ secs_per_month = 30 * SECS_PER_DAY;
+ }
+ else
+ {
+
+ /* the other months */
+ secs_per_month = 31 * SECS_PER_DAY;
+ }
+ }
+
+ /* determine current day of the month */
+ day = secs_low / SECS_PER_DAY;
+ secs_low -= day * SECS_PER_DAY;
+
+ /* determine current hour */
+ hour = secs_low / SECS_PER_HOUR;
+ secs_low -= hour * SECS_PER_HOUR;
+
+ /* determine current minute */
+ minute = secs_low / SECS_PER_MINUTE;
+ secs_low -= minute * SECS_PER_MINUTE;
+
+ /* return date */
+ date_time_ptr -> year = year;
+ date_time_ptr -> month = (UCHAR)month;
+ date_time_ptr -> day = (UCHAR)(day + 1);
+ date_time_ptr -> hour = (UCHAR)hour;
+ date_time_ptr -> minute = (UCHAR)minute;
+ date_time_ptr -> second = (UCHAR)secs_low;
+ date_time_ptr -> weekday = (UCHAR)weekday;
+ date_time_ptr -> nanosecond = (ULONG)time_ptr -> nanosecond;
+
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_add64 PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function adds two 64-bit numbers: A = A + B. */
+/* */
+/* INPUT */
+/* */
+/* a_hi Pointer to higher 32-bit of A */
+/* a_lo Pointer to lower 32-bit of A */
+/* b_hi higher 32-bit of B */
+/* b_lo lower 32-bit of B */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_clock_adjust Adjust PTP clock */
+/* _nx_ptp_client_utility_convert_time_to_date */
+/* Convert time to date */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo)
+{
+LONG r_hi;
+ULONG r_lo;
+
+ r_hi = *a_hi + b_hi;
+ r_lo = *a_lo + b_lo;
+ if (r_lo < *a_lo)
+ {
+ r_hi++; /* add carry */
+ }
+ *a_hi = r_hi;
+ *a_lo = r_lo;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_sub64 PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function substracts two 64-bit numbers: A = A - B. */
+/* */
+/* INPUT */
+/* */
+/* a_hi Pointer to higher 32-bit of A */
+/* a_lo Pointer to lower 32-bit of A */
+/* b_hi higher 32-bit of B */
+/* b_lo lower 32-bit of B */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_utility_time_diff Diff two PTP times */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo)
+{
+LONG r_hi;
+ULONG r_lo;
+
+ r_hi = *a_hi - b_hi;
+ r_lo = *a_lo - b_lo;
+ if (*a_lo < b_lo)
+ {
+ r_hi--; /* substract carry */
+ }
+ *a_hi = r_hi;
+ *a_lo = r_lo;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_inc64 PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function increments a 64-bit number: A = A + 1. */
+/* */
+/* INPUT */
+/* */
+/* a_hi Pointer to higher 32-bit of A */
+/* a_lo Pointer to lower 32-bit of A */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */
+/* _nx_ptp_client_clock_adjust Adjust PTP clock */
+/* _nx_ptp_client_utility_time_diff Diff two PTP times */
+/* _nx_ptp_client_soft_clock_callback Soft PTP clock */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo)
+{
+ULONG r_lo;
+
+ r_lo = *a_lo + 1;
+ if (r_lo == 0)
+ {
+ *a_hi = *a_hi + 1; /* add carry */
+ }
+ *a_lo = r_lo;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_dec64 PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function decrements a 64-bit number: A = A - 1. */
+/* */
+/* INPUT */
+/* */
+/* a_hi Pointer to higher 32-bit of A */
+/* a_lo Pointer to lower 32-bit of A */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */
+/* _nx_ptp_client_clock_adjust Adjust PTP clock */
+/* _nx_ptp_client_utility_time_diff Diff two PTP times */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo)
+{
+ULONG r_lo;
+
+ r_lo = *a_lo;
+ if (r_lo == 0)
+ {
+ *a_hi = *a_hi - 1; /* substract carry */
+ }
+ *a_lo = r_lo - 1;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_neg64 PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function changes the sign of a 64-bit number: A = -A. */
+/* */
+/* INPUT */
+/* */
+/* a_hi Pointer to higher 32-bit of A */
+/* a_lo Pointer to lower 32-bit of A */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo)
+{
+LONG r_hi;
+
+ r_hi = -*a_hi;
+ if (*a_lo != 0)
+ {
+ r_hi--; /* substract carry */
+ }
+ *a_hi = r_hi;
+ *a_lo = -*a_lo;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_ptp_client_utility_time_div_by_2 PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function divides a PTP time by 2. */
+/* */
+/* INPUT */
+/* */
+/* time_ptr Pointer to PTP time */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_ptp_client_utility_neg64 Change the sign of number */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_ptp_client_delay_resp_received Process delay response */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr)
+{
+UINT neg;
+LONG sec_hi;
+ULONG sec_lo;
+LONG ns;
+
+ /* get current time value */
+ sec_hi = time_ptr -> second_high;
+ sec_lo = time_ptr -> second_low;
+ ns = time_ptr -> nanosecond;
+
+ /* implement division on unsigned values */
+ if ((sec_hi < 0) || (ns < 0))
+ {
+ _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo);
+ ns = -ns;
+ neg = 1;
+ }
+ else
+ {
+ neg = 0;
+ }
+
+ /* divide nanoseconds by two */
+ ns >>= 1;
+ if (sec_lo & 1)
+ {
+
+ /* add rest of seconds division */
+ ns += 500000000L;
+ }
+
+ /* divide seconds by two */
+ sec_lo >>= 1;
+ if (sec_hi & 1)
+ {
+ sec_lo |= 0x80000000UL;
+ }
+ sec_hi >>= 1;
+
+ /* restore sign */
+ if (neg)
+ {
+ _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo);
+ ns = -ns;
+ }
+
+ /* return result */
+ time_ptr -> second_high = sec_hi;
+ time_ptr -> second_low = sec_lo;
+ time_ptr -> nanosecond = ns;
+}
diff --git a/addons/ptp/nxd_ptp_client.h b/addons/ptp/nxd_ptp_client.h
new file mode 100644
index 00000000..3524b860
--- /dev/null
+++ b/addons/ptp/nxd_ptp_client.h
@@ -0,0 +1,482 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX PTP Client Component */
+/** */
+/** Precision Time Protocol (PTP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* APPLICATION INTERFACE DEFINITION RELEASE */
+/* */
+/* nxd_ptp_client.h PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the NetX Precision Time Protocol (PTP) */
+/* Client component, including all data types and external references. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NXD_PTP_CLIENT_H
+#define NXD_PTP_CLIENT_H
+
+
+/* Include NetX and ThreadX definitions */
+
+#include "nx_api.h"
+
+
+/* Determine if a C++ compiler is being used. If so, ensure that standard
+ C is used to process the API information. */
+
+#ifdef __cplusplus
+
+/* Yes, C++ compiler is present. Use standard C. */
+extern "C" {
+
+#endif
+
+
+/* PTP Client configurable options. */
+
+
+/* Set the client thread time slice. */
+
+#ifndef NX_PTP_CLIENT_THREAD_TIME_SLICE
+#define NX_PTP_CLIENT_THREAD_TIME_SLICE TX_NO_TIME_SLICE
+#endif
+
+
+/* Define the PTP Client ID */
+
+#define NX_PTP_CLIENT_ID 0x50545001UL
+
+
+/* Define the PTP client internal timer frequency */
+
+#ifndef NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND
+#define NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND 10
+#endif
+
+
+/* Define the maximum number of missing Announce packets before timeout */
+
+#ifndef NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT
+#define NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT 3
+#endif
+
+
+/* Define the time interval between successive Announce packet, expressed as log 2.
+ This value should be uniform throughout a domain. The default value is 1=2s. */
+
+#ifndef NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL
+#define NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL 1
+#endif
+
+
+/* Define the interval for sending Delay request packets */
+
+#ifndef NX_PTP_CLIENT_DELAY_REQ_INTERVAL
+#define NX_PTP_CLIENT_DELAY_REQ_INTERVAL (2 * NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND)
+#endif
+
+
+/* Set maximum queue depth for client socket.*/
+
+#ifndef NX_PTP_CLIENT_MAX_QUEUE_DEPTH
+#define NX_PTP_CLIENT_MAX_QUEUE_DEPTH 5
+#endif
+
+/* Define the maximum size of a PTP message */
+
+#define NX_PTP_CLIENT_PACKET_DATA_SIZE 64
+
+/* Define Announce receipt timeout expire value */
+#define NX_PTP_CLIENT_ANNOUNCE_EXPIRATION (NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT * \
+ (1 << NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL) * \
+ NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND)
+
+
+/* Define a PTP Time */
+
+typedef struct NX_PTP_TIME_STRUCT
+{
+ /* The MSB of the number of seconds */
+ LONG second_high;
+
+ /* The LSB of the number of seconds */
+ ULONG second_low;
+
+ /* The number of nanoseconds */
+ LONG nanosecond;
+} NX_PTP_TIME;
+
+
+/* Define the PTP Date Time structure. */
+
+typedef struct NX_PTP_DATE_TIME_STRUCT
+{
+ UINT year;
+ UCHAR month;
+ UCHAR day;
+ UCHAR hour;
+ UCHAR minute;
+ UCHAR second;
+ UCHAR weekday;
+ ULONG nanosecond;
+} NX_PTP_DATE_TIME;
+
+
+/* Internal PTP error processing codes. */
+
+#define NX_PTP_ERROR_CONSTANT 0xD00
+/* Client side errors. */
+#define NX_PTP_CLIENT_NOT_STARTED (NX_PTP_ERROR_CONSTANT | 0x01) /* PTP Client task is not running */
+#define NX_PTP_CLIENT_ALREADY_STARTED (NX_PTP_ERROR_CONSTANT | 0x02) /* PTP Client task is already running */
+#define NX_PTP_PARAM_ERROR (NX_PTP_ERROR_CONSTANT | 0x03) /* Invalid non pointer parameter. */
+#define NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD (NX_PTP_ERROR_CONSTANT | 0x04) /* Client not properly initialized to receive time data. */
+#define NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE (NX_PTP_ERROR_CONSTANT | 0x05) /* PTP clock callback returns error. */
+
+
+/* PTP Protocol Definitions */
+
+/* Define the size of the PTP Clock Identity field */
+#define NX_PTP_CLOCK_IDENTITY_SIZE 8
+
+/* Define the size of the PTP Clock Port and Identity field */
+#define NX_PTP_CLOCK_PORT_IDENTITY_SIZE (NX_PTP_CLOCK_IDENTITY_SIZE + 2)
+
+
+/* PTP event callback */
+
+struct NX_PTP_CLIENT_STRUCT;
+
+typedef UINT (*NX_PTP_CLIENT_EVENT_CALLBACK)(struct NX_PTP_CLIENT_STRUCT *client_ptr, UINT event,
+ VOID *event_data, VOID *callback_data);
+
+#define NX_PTP_CLIENT_EVENT_MASTER 0
+#define NX_PTP_CLIENT_EVENT_SYNC 1
+#define NX_PTP_CLIENT_EVENT_TIMEOUT 2
+
+
+/* PTP clock callback operations */
+
+typedef UINT (*NX_PTP_CLIENT_CLOCK_CALLBACK)(struct NX_PTP_CLIENT_STRUCT *client_ptr, UINT operation,
+ NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, VOID *callback_data);
+
+#define NX_PTP_CLIENT_CLOCK_INIT 0 /* Initialization */
+#define NX_PTP_CLIENT_CLOCK_SET 1 /* Set the PTP clock */
+#define NX_PTP_CLIENT_CLOCK_GET 2 /* Get the PTP clock */
+#define NX_PTP_CLIENT_CLOCK_ADJUST 3 /* Adjust the PTP clock */
+#define NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT 4 /* Extract timestamp from packet */
+#define NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE 5 /* Prepare timestamp for packet */
+#define NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE 6 /* Update timer for soft implementation */
+
+
+/* Master messages data */
+typedef struct NX_PTP_CLIENT_MASTER_STRUCT
+{
+ NXD_ADDRESS *nx_ptp_client_master_address;
+ UCHAR *nx_ptp_client_master_port_identity;
+ UCHAR nx_ptp_client_master_priority1;
+ UCHAR nx_ptp_client_master_priority2;
+ UCHAR nx_ptp_client_master_clock_class;
+ UCHAR nx_ptp_client_master_clock_accuracy;
+ USHORT nx_ptp_client_master_offset_scaled_log_variance;
+ UCHAR *nx_ptp_client_master_grandmaster_identity;
+ USHORT nx_ptp_client_master_steps_removed;
+ UCHAR nx_ptp_client_master_time_source;
+} NX_PTP_CLIENT_MASTER;
+
+/* Sync flags */
+#define NX_PTP_CLIENT_SYNC_CALIBRATED (1 << 0)
+#define NX_PTP_CLIENT_SYNC_UTC_REASONABLE (1 << 1)
+#define NX_PTP_CLIENT_SYNC_LEAP59 (1 << 2)
+#define NX_PTP_CLIENT_SYNC_LEAP61 (1 << 3)
+
+/* Sync message data */
+typedef struct NX_PTP_CLIENT_SYNC_STRUCT
+{
+ USHORT nx_ptp_client_sync_flags;
+ SHORT nx_ptp_client_sync_utc_offset;
+} NX_PTP_CLIENT_SYNC;
+
+
+/* Define the Type of messages */
+
+#define NX_PTP_CLIENT_ALL_EVENTS 0xFFFFFFFF /* all events of PTP client */
+#define NX_PTP_CLIENT_STOP_EVENT 0x00000001 /* stop the PTP client */
+#define NX_PTP_CLIENT_RX_EVENT 0x00000002 /* received UDP packet */
+#define NX_PTP_CLIENT_TIMER_EVENT 0x00000004 /* timer tick */
+
+
+/* Define the size of the PTP client message queue */
+
+#define NX_PTP_CLIENT_MESSAGE_QUEUE_SIZE 16
+
+
+/* Define the state of the PTP Client thread */
+
+#define NX_PTP_CLIENT_THREAD_IDLE 0
+#define NX_PTP_CLIENT_THREAD_RUNNING 1
+#define NX_PTP_CLIENT_THREAD_STOPPING 2
+#define NX_PTP_CLIENT_THREAD_STOPPED 3
+
+
+/* Define the state of the PTP Client clock */
+
+#define NX_PTP_CLIENT_STATE_LISTENING 0
+#define NX_PTP_CLIENT_STATE_WAIT_SYNC 1
+#define NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP 2
+
+
+/* Define the state of the delay measurement process */
+
+#define NX_PTP_CLIENT_DELAY_IDLE 0
+#define NX_PTP_CLIENT_DELAY_WAIT_REQ_TS 1
+#define NX_PTP_CLIENT_DELAY_WAIT_RESP 2
+
+
+/* Define the structure of a PTP Client */
+
+typedef struct NX_PTP_CLIENT_STRUCT
+{
+ /* PTP Client ID */
+ ULONG nx_ptp_client_id;
+
+ /* Pointer to the Client IP instance. */
+ NX_IP *nx_ptp_client_ip_ptr;
+
+ /* Index to PTP network interface */
+ UINT nx_ptp_client_interface_index;
+
+ /* Pointer to the Client packet pool. */
+ NX_PACKET_POOL *nx_ptp_client_packet_pool_ptr;
+
+ /* PTP Domain Number */
+ UCHAR nx_ptp_client_domain;
+
+ /* PTP Transport Specific */
+ UCHAR nx_ptp_client_transport_specific;
+
+ /* PTP Client Port and Identity */
+ UCHAR nx_ptp_client_port_identity[NX_PTP_CLOCK_PORT_IDENTITY_SIZE];
+
+ /* PTP event handler callback */
+ NX_PTP_CLIENT_EVENT_CALLBACK nx_ptp_client_event_callback;
+ VOID *nx_ptp_client_event_callback_data;
+
+ /* PTP clock callback */
+ NX_PTP_CLIENT_CLOCK_CALLBACK nx_ptp_client_clock_callback;
+ VOID *nx_ptp_client_clock_callback_data;
+
+ /* PTP General Messages UDP Socket */
+ NX_UDP_SOCKET nx_ptp_client_general_socket;
+
+ /* PTP Event Messages UDP Socket */
+ NX_UDP_SOCKET nx_ptp_client_event_socket;
+
+ /* The message queue */
+ TX_EVENT_FLAGS_GROUP nx_ptp_client_events;
+
+ /* Set if IPv4 multicast group has been joined */
+ UCHAR nx_ptp_client_ipv4_group_joined;
+
+#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
+ /* Set if IPv6 multicast group has been joined */
+ UCHAR nx_ptp_client_ipv6_group_joined;
+#endif
+
+ /* The software clock value */
+ NX_PTP_TIME nx_ptp_client_soft_clock;
+
+ /* The state of the PTP client */
+ UCHAR nx_ptp_client_state;
+
+ /* The state of the delay measurement */
+ UCHAR nx_ptp_client_delay_state;
+
+ /* The current UTC offset flags */
+ USHORT nx_ptp_client_sync_flags;
+
+ /* The current UTC offset */
+ SHORT nx_ptp_client_utc_offset;
+
+ /* The address of the master clock */
+ NXD_ADDRESS nx_ptp_client_master_addr;
+
+ /* The identity of the master clock */
+ UCHAR nx_ptp_client_master_port_identity[NX_PTP_CLOCK_PORT_IDENTITY_SIZE];
+
+ /* The current sync master timestamp */
+ NX_PTP_TIME nx_ptp_client_sync;
+
+ /* The current sync client timestamp */
+ NX_PTP_TIME nx_ptp_client_sync_ts;
+
+ /* The id of the sync message */
+ USHORT nx_ptp_client_sync_id;
+
+ /* The id of the last delay_req message */
+ USHORT nx_ptp_client_delay_req_id;
+
+ /* The delay request interval timer */
+ INT nx_ptp_client_delay_req_timer;
+
+ /* The Announce timeout */
+ INT nx_ptp_client_announce_timeout;
+
+ /* The delay request flag */
+ UINT nx_ptp_client_delay_req_flag;
+
+ /* The delay request client timestamp */
+ NX_PTP_TIME nx_ptp_client_delay_ts;
+
+ /* The delay request packet pointer */
+ NX_PACKET *nx_ptp_client_delay_req_packet_ptr;
+
+ /* The PTP client timer */
+ TX_TIMER nx_ptp_client_timer;
+
+ /* The current state of the PTP Client thread */
+ UINT nx_ptp_client_thread_state;
+
+ /* The PTP client processing thread */
+ TX_THREAD nx_ptp_client_thread;
+} NX_PTP_CLIENT;
+
+
+#ifndef NX_PTP_SOURCE_CODE
+
+/* Define the system API mappings based on the error checking selected by the user. */
+
+/* Determine if error checking is desired. If so, map API functions
+ to the appropriate error checking front-ends. Otherwise, map API
+ functions to the core functions that actually perform the work.
+ Note: error checking is enabled by default. */
+
+
+#ifdef NX_PTP_DISABLE_ERROR_CHECKING
+
+/* Services without error checking. */
+
+#define nx_ptp_client_create _nx_ptp_client_create
+#define nx_ptp_client_delete _nx_ptp_client_delete
+#define nx_ptp_client_start _nx_ptp_client_start
+#define nx_ptp_client_stop _nx_ptp_client_stop
+#define nx_ptp_client_time_get _nx_ptp_client_time_get
+#define nx_ptp_client_time_set _nx_ptp_client_time_set
+#define nx_ptp_client_master_info_get _nx_ptp_client_master_info_get
+#define nx_ptp_client_sync_info_get _nx_ptp_client_sync_info_get
+#define nx_ptp_client_packet_timestamp_notify _nx_ptp_client_packet_timestamp_notify
+#define nx_ptp_client_soft_clock_callback _nx_ptp_client_soft_clock_callback
+#define nx_ptp_client_utility_time_diff _nx_ptp_client_utility_time_diff
+#define nx_ptp_client_utility_convert_time_to_date _nx_ptp_client_utility_convert_time_to_date
+
+#else
+
+/* Services with error checking. */
+
+#define nx_ptp_client_create _nxe_ptp_client_create
+#define nx_ptp_client_delete _nxe_ptp_client_delete
+#define nx_ptp_client_start _nxe_ptp_client_start
+#define nx_ptp_client_stop _nxe_ptp_client_stop
+#define nx_ptp_client_time_get _nxe_ptp_client_time_get
+#define nx_ptp_client_time_set _nxe_ptp_client_time_set
+#define nx_ptp_client_master_info_get _nxe_ptp_client_master_info_get
+#define nx_ptp_client_sync_info_get _nxe_ptp_client_sync_info_get
+#define nx_ptp_client_packet_timestamp_notify _nx_ptp_client_packet_timestamp_notify
+#define nx_ptp_client_soft_clock_callback _nx_ptp_client_soft_clock_callback
+#define nx_ptp_client_utility_time_diff _nxe_ptp_client_utility_time_diff
+#define nx_ptp_client_utility_convert_time_to_date _nxe_ptp_client_utility_convert_time_to_date
+
+#endif
+
+#endif
+
+
+/* Define the function prototypes of the PTP Client API */
+
+UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
+ NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
+ NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data);
+UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr);
+UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
+ UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
+ VOID *event_callback_data);
+UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr);
+UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr);
+UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr);
+UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
+ UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
+ UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
+ UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source);
+UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset);
+UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr);
+UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr);
+VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr);
+UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation,
+ NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr,
+ VOID *callback_data);
+
+UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
+ NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
+ NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data);
+UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr);
+UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
+ UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
+ VOID *event_callback_data);
+UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr);
+UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr);
+UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr);
+UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
+ UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
+ UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
+ UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source);
+UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset);
+UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr);
+UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr);
+
+
+/* Define the function prototypes of the private utility functions */
+
+VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr);
+VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo);
+VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo);
+VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo);
+VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo);
+VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo);
+
+
+/* Determine if a C++ compiler is being used. If so, complete the standard
+ C conditional started above. */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NX_PTP_CLIENT_H */
diff --git a/common/inc/nx_api.h b/common/inc/nx_api.h
index cd56b4eb..a48e15b4 100644
--- a/common/inc/nx_api.h
+++ b/common/inc/nx_api.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nx_api.h PORTABLE C */
-/* 6.1.2 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -52,6 +52,12 @@
/* 11-09-2020 Yuxin Zhou Modified comment(s), and */
/* updated product constants, */
/* resulting in version 6.1.2 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), added */
+/* PTP timestamp capability, */
+/* added function to convert */
+/* string to unsigned integer, */
+/* updated product constants, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -459,7 +465,7 @@ VOID _nx_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG
#define AZURE_RTOS_NETXDUO
#define NETXDUO_MAJOR_VERSION 6
#define NETXDUO_MINOR_VERSION 1
-#define NETXDUO_PATCH_VERSION 2
+#define NETXDUO_PATCH_VERSION 3
/* Define the following symbols for backward compatibility */
#define EL_PRODUCT_NETXDUO
@@ -1301,6 +1307,7 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT
#define NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM 0x00000200
#define NX_INTERFACE_CAPABILITY_IGMP_TX_CHECKSUM 0x00000400
#define NX_INTERFACE_CAPABILITY_IGMP_RX_CHECKSUM 0x00000800
+#define NX_INTERFACE_CAPABILITY_PTP_TIMESTAMP 0x00001000
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */
#define NX_IP_VERSION_V4 0x4
@@ -3803,6 +3810,7 @@ VOID _nx_ip_driver_link_status_event(NX_IP *ip_ptr, UINT interface_index);
/* Utility functions. */
UINT _nx_utility_string_length_check(CHAR *input_string, UINT *string_length, UINT max_string_length);
+UINT _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number);
/* Determine if a C++ compiler is being used. If so, complete the standard
C conditional started above. */
diff --git a/common/src/nx_ipv6_process_hop_by_hop_option.c b/common/src/nx_ipv6_process_hop_by_hop_option.c
index cef14f7b..c5881662 100644
--- a/common/src/nx_ipv6_process_hop_by_hop_option.c
+++ b/common/src/nx_ipv6_process_hop_by_hop_option.c
@@ -38,7 +38,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ipv6_process_hop_by_hop_option PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -73,6 +73,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
+/* buffer read overflow check, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_ipv6_process_hop_by_hop_option(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -87,6 +90,14 @@ NX_IPV6_HOP_BY_HOP_OPTION *option;
/* Add debug information. */
NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
+ /* Make sure there's no OOB when reading Hdr Ext Len from the packet buffer. */
+ if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < 2)
+ {
+
+ /* return an error code. */
+ return(NX_OPTION_HEADER_ERROR);
+ }
+
/* Read the Hdr Ext Len field. */
header_length = *(packet_ptr -> nx_packet_prepend_ptr + 1);
diff --git a/common/src/nx_utility.c b/common/src/nx_utility.c
index eb2aac31..60e750b7 100644
--- a/common/src/nx_utility.c
+++ b/common/src/nx_utility.c
@@ -107,3 +107,93 @@ UINT i;
return(NX_SUCCESS);
}
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_utility_string_to_uint PORTABLE C */
+/* 6.1.3 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function converts the string to unsigned integer. */
+/* */
+/* INPUT */
+/* */
+/* input_string Pointer to input string */
+/* string_length Length of input string */
+/* number Pointer to the number */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+UINT _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number)
+{
+
+UINT i;
+
+
+ /* Check for invalid input pointers. */
+ if ((input_string == NX_NULL) || (number == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check string length. */
+ if (string_length == 0)
+ {
+ return(NX_SIZE_ERROR);
+ }
+
+ /* Initialize. */
+ i = 0;
+ *number = 0;
+
+ /* Traverse the string. */
+ while (i < string_length)
+ {
+
+ /* Is a numeric character present? */
+ if ((input_string[i] >= '0') && (input_string[i] <= '9'))
+ {
+
+ /* Check overflow. Max Value: Hex:0xFFFFFFFF, Decimal: 4294967295. */
+ if (((*number == 429496729) && (input_string[i] > '5')) ||
+ (*number >= 429496730))
+ {
+ return(NX_OVERFLOW);
+ }
+
+ /* Yes, numeric character is present. Update the number. */
+ *number = (*number * 10) + (UINT) (input_string[i] - '0');
+ }
+ else
+ {
+ return(NX_INVALID_PARAMETERS);
+ }
+
+ i++;
+ }
+
+ /* Return success. */
+ return(NX_SUCCESS);
+}
diff --git a/nx_secure/inc/nx_secure_dtls.h b/nx_secure/inc/nx_secure_dtls.h
index c1de4f47..f2fb6d75 100644
--- a/nx_secure/inc/nx_secure_dtls.h
+++ b/nx_secure/inc/nx_secure_dtls.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_secure_dtls.h PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -43,6 +43,10 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -437,7 +441,7 @@ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHA
UINT _nx_secure_dtls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type,
- USHORT *header_size, UINT *message_length,
+ UINT *header_size, UINT *message_length,
UINT *message_seq, UINT *fragment_offset,
UINT *fragment_length);
@@ -463,7 +467,7 @@ UINT _nx_secure_dtls_send_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET
UCHAR record_type, ULONG wait_option);
UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
- ULONG wait_option);
+ UINT data_length, ULONG wait_option);
UINT _nx_secure_dtls_send_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *send_packet);
diff --git a/nx_secure/inc/nx_secure_tls.h b/nx_secure/inc/nx_secure_tls.h
index 7eb5892d..ef3f8975 100644
--- a/nx_secure/inc/nx_secure_tls.h
+++ b/nx_secure/inc/nx_secure_tls.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_secure_tls.h PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -52,6 +52,11 @@
/* bug, fixed certificate */
/* buffer allocation, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* updated product constants, */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -112,7 +117,7 @@ extern "C" {
#define AZURE_RTOS_NETX_SECURE
#define NETX_SECURE_MAJOR_VERSION 6
#define NETX_SECURE_MINOR_VERSION 1
-#define NETX_SECURE_PATCH_VERSION 0
+#define NETX_SECURE_PATCH_VERSION 3
/* The following symbols are defined for backward compatibility reasons. */
#define EL_PRODUCT_NETX_SECURE
@@ -1390,7 +1395,7 @@ UINT _nx_secure_tls_process_header(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET
ULONG record_offset, USHORT *message_type, UINT *length,
UCHAR *header_data, USHORT *header_length);
UINT _nx_secure_tls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type,
- USHORT *header_size, UINT *message_length);
+ UINT *header_size, UINT *message_length);
UINT _nx_secure_tls_process_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *packet_ptr,
ULONG *bytes_processed, ULONG wait_option);
UINT _nx_secure_tls_process_remote_certificate(NX_SECURE_TLS_SESSION *tls_session,
diff --git a/nx_secure/src/nx_secure_dtls_client_handshake.c b/nx_secure/src/nx_secure_dtls_client_handshake.c
index a6ad765e..57b71772 100644
--- a/nx_secure/src/nx_secure_dtls_client_handshake.c
+++ b/nx_secure/src/nx_secure_dtls_client_handshake.c
@@ -32,7 +32,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_client_handshake PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -110,6 +110,11 @@
/* fixed certificate buffer */
/* allocation, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, added null */
+/* pointer checking, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
@@ -118,7 +123,7 @@ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHA
#ifndef NX_SECURE_TLS_CLIENT_DISABLED
UINT status;
USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE;
-USHORT header_bytes;
+UINT header_bytes;
UINT message_length;
UCHAR *data_start = NX_NULL;
NX_PACKET *send_packet = NX_NULL;
@@ -146,6 +151,7 @@ NX_SECURE_TLS_SESSION *tls_session;
while (data_length > 0)
{
+ header_bytes = data_length;
/* First, process the handshake message to get our state and any data therein. */
status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes,
@@ -169,6 +175,12 @@ NX_SECURE_TLS_SESSION *tls_session;
return(NX_SUCCESS);
}
+ /* Check the fragment_length with the lenght of packet buffer. */
+ if ((header_bytes + fragment_length) > data_length)
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
/* Check available area of buffer. */
if ((fragment_offset + fragment_length) > tls_session -> nx_secure_tls_packet_buffer_size ||
(header_bytes + message_length) > tls_session -> nx_secure_tls_packet_buffer_size)
@@ -381,7 +393,7 @@ NX_SECURE_TLS_SESSION *tls_session;
/* Get ClientHello packet from header of transmit queue. */
send_packet = dtls_session -> nx_secure_dtls_transmit_sent_head;
- if (send_packet -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE))
+ if ((send_packet == NX_NULL) || (send_packet -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE)))
{
/* Invalid packet. */
@@ -592,8 +604,8 @@ NX_SECURE_TLS_SESSION *tls_session;
return(error_number);
}
- /* Advance the buffer pointer past the message. */
- packet_buffer += (message_length + header_bytes);
+ /* Advance the buffer pointer past the fragment. */
+ packet_buffer += (fragment_length + header_bytes);
} /* End while. */
return(NX_SUCCESS);
#else /* TLS Client disabled. */
diff --git a/nx_secure/src/nx_secure_dtls_process_clienthello.c b/nx_secure/src/nx_secure_dtls_process_clienthello.c
index dae013b1..08fb37be 100644
--- a/nx_secure/src/nx_secure_dtls_process_clienthello.c
+++ b/nx_secure/src/nx_secure_dtls_process_clienthello.c
@@ -40,7 +40,7 @@ static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_IN
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_process_clienthello PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -90,6 +90,10 @@ static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_IN
/* renegotiation bug, */
/* improved negotiation logic, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_process_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
@@ -243,6 +247,12 @@ NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data;
compression_methods_length = packet_buffer[0];
packet_buffer += 1;
+ /* Message length overflow. */
+ if (((UINT)(packet_buffer - packet_buffer_start + compression_methods_length)) > message_length)
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
/* Make sure NULL compression method is supported. */
status = NX_SECURE_TLS_BAD_COMPRESSION_METHOD;
for (i = 0; i < compression_methods_length; ++i)
diff --git a/nx_secure/src/nx_secure_dtls_process_handshake_header.c b/nx_secure/src/nx_secure_dtls_process_handshake_header.c
index ec08cc95..69fe356d 100644
--- a/nx_secure/src/nx_secure_dtls_process_handshake_header.c
+++ b/nx_secure/src/nx_secure_dtls_process_handshake_header.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_process_handshake_header PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -45,7 +45,8 @@
/* */
/* packet_buffer Pointer to incoming packet */
/* message_type Return message type value */
-/* header_size Return size of header */
+/* header_size Input size of packet buffer */
+/* Return size of header */
/* message_length Return length of message */
/* message_seq Return sequence of message */
/* fragment_offset Return offset of fragment */
@@ -71,13 +72,24 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type,
- USHORT *header_size, UINT *message_length,
+ UINT *header_size, UINT *message_length,
UINT *message_seq, UINT *fragment_offset,
UINT *fragment_length)
{
+
+ /* Check buffer length. */
+ if (*header_size < NX_SECURE_DTLS_HANDSHAKE_HEADER_SIZE)
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
/* The message being passed in to this function should already be stripped of the TLS header
so the first byte in the packet/record is our handshake message type. */
*message_type = packet_buffer[0];
diff --git a/nx_secure/src/nx_secure_dtls_process_record.c b/nx_secure/src/nx_secure_dtls_process_record.c
index 906eb1e1..d5ef73b1 100644
--- a/nx_secure/src/nx_secure_dtls_process_record.c
+++ b/nx_secure/src/nx_secure_dtls_process_record.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_process_record PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -80,6 +80,10 @@
/* adjusted logic for TLS */
/* modifications, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_process_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *packet_ptr,
@@ -246,7 +250,7 @@ NX_PACKET *decrypted_packet;
/* The socket is a TLS server, so process incoming handshake messages in that context. */
if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
{
- status = _nx_secure_dtls_server_handshake(dtls_session, packet_data, wait_option);
+ status = _nx_secure_dtls_server_handshake(dtls_session, packet_data, message_length, wait_option);
}
#endif
#ifndef NX_SECURE_TLS_CLIENT_DISABLED
diff --git a/nx_secure/src/nx_secure_dtls_server_handshake.c b/nx_secure/src/nx_secure_dtls_server_handshake.c
index b437bf33..640edd7a 100644
--- a/nx_secure/src/nx_secure_dtls_server_handshake.c
+++ b/nx_secure/src/nx_secure_dtls_server_handshake.c
@@ -33,7 +33,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_server_handshake PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -48,6 +48,7 @@
/* */
/* dtls_session TLS control block */
/* packet_buffer Pointer into record buffer */
+/* data_length Length of data */
/* wait_option Controls timeout actions */
/* */
/* OUTPUT */
@@ -110,15 +111,19 @@
/* fixed certificate buffer */
/* allocation, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
- ULONG wait_option)
+ UINT data_length, ULONG wait_option)
{
#ifndef NX_SECURE_TLS_SERVER_DISABLED
UINT status;
USHORT message_type;
-USHORT header_bytes;
+UINT header_bytes;
UINT message_length;
UINT message_seq;
UINT fragment_offset;
@@ -150,6 +155,8 @@ UCHAR *fragment_buffer;
/* Use the TLS packet buffer for fragment processing. */
fragment_buffer = tls_session->nx_secure_tls_packet_buffer;
+ header_bytes = data_length;
+
/* First, process the handshake message to get our state and any data therein. */
status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes,
&message_length, &message_seq, &fragment_offset, &fragment_length);
@@ -178,6 +185,12 @@ UCHAR *fragment_buffer;
return(1);
}
+ /* Check the fragment_length with the lenght of packet buffer. */
+ if ((header_bytes + fragment_length) > data_length)
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
/* Check available area of buffer. */
if ((fragment_offset + fragment_length) > tls_session -> nx_secure_tls_packet_buffer_size ||
(header_bytes + message_length) > tls_session -> nx_secure_tls_packet_buffer_size)
diff --git a/nx_secure/src/nx_secure_tls_1_3_client_handshake.c b/nx_secure/src/nx_secure_tls_1_3_client_handshake.c
index fcb16303..4c352911 100644
--- a/nx_secure/src/nx_secure_tls_1_3_client_handshake.c
+++ b/nx_secure/src/nx_secure_tls_1_3_client_handshake.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_1_3_client_handshake PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -108,6 +108,10 @@
/* fixed certificate buffer */
/* allocation, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -141,7 +145,7 @@ UINT _nx_secure_tls_1_3_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCH
#ifndef NX_SECURE_TLS_CLIENT_DISABLED
UINT status;
USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE;
-USHORT header_bytes;
+UINT header_bytes;
UINT message_length;
UINT packet_buffer_length = data_length;
UCHAR *packet_start;
@@ -215,8 +219,15 @@ const UCHAR *server_random;
* so we can hash it. */
packet_start = packet_buffer;
+ header_bytes = data_length;
+
/* First, process the handshake message to get our state and any data therein. */
- _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+ status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+
+ if (status != NX_SECURE_TLS_SUCCESS)
+ {
+ return(status);
+ }
/* Check for fragmented records. */
if((message_length + header_bytes) > data_length)
diff --git a/nx_secure/src/nx_secure_tls_1_3_server_handshake.c b/nx_secure/src/nx_secure_tls_1_3_server_handshake.c
index 20eacdfe..4e78db77 100644
--- a/nx_secure/src/nx_secure_tls_1_3_server_handshake.c
+++ b/nx_secure/src/nx_secure_tls_1_3_server_handshake.c
@@ -31,7 +31,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_server_handshake PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -99,6 +99,10 @@
/* fixed certificate buffer */
/* allocation, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
#if (NX_SECURE_TLS_TLS_1_3_ENABLED)
@@ -108,7 +112,7 @@ UINT _nx_secure_tls_1_3_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCH
#ifndef NX_SECURE_TLS_SERVER_DISABLED
UINT status;
USHORT message_type;
-USHORT header_bytes;
+UINT header_bytes;
UINT message_length;
NX_PACKET *send_packet;
NX_PACKET_POOL *packet_pool;
@@ -175,7 +179,14 @@ NX_SECURE_TLS_SERVER_STATE old_server_state;
/* Save a pointer to the start of our packet for the hash that happens below. */
packet_start = packet_buffer;
- _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+ header_bytes = data_length;
+
+ status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+
+ if (status != NX_SECURE_TLS_SUCCESS)
+ {
+ return(status);
+ }
/* Check for fragmented records. */
if((message_length + header_bytes) > data_length)
diff --git a/nx_secure/src/nx_secure_tls_client_handshake.c b/nx_secure/src/nx_secure_tls_client_handshake.c
index fb269fd1..f7792505 100644
--- a/nx_secure/src/nx_secure_tls_client_handshake.c
+++ b/nx_secure/src/nx_secure_tls_client_handshake.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_client_handshake PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -107,6 +107,10 @@
/* fixed certificate buffer */
/* allocation, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer,
@@ -116,7 +120,7 @@ UINT _nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *
UINT status;
UINT temp_status;
USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE;
-USHORT header_bytes;
+UINT header_bytes;
UINT message_length;
UINT packet_buffer_length = data_length;
UCHAR *packet_start;
@@ -142,8 +146,15 @@ const NX_CRYPTO_METHOD
* so we can hash it. */
packet_start = packet_buffer;
+ header_bytes = data_length;
+
/* First, process the handshake message to get our state and any data therein. */
- _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+ status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+
+ if (status != NX_SECURE_TLS_SUCCESS)
+ {
+ return(status);
+ }
/* Check for fragmented records. */
if((message_length + header_bytes) > data_length)
diff --git a/nx_secure/src/nx_secure_tls_process_handshake_header.c b/nx_secure/src/nx_secure_tls_process_handshake_header.c
index b28a398e..226362eb 100644
--- a/nx_secure/src/nx_secure_tls_process_handshake_header.c
+++ b/nx_secure/src/nx_secure_tls_process_handshake_header.c
@@ -31,7 +31,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_process_handshake_header PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -46,7 +46,8 @@
/* */
/* packet_buffer Pointer to incoming packet */
/* message_type Return message type value */
-/* header_size Return size of header */
+/* header_size Input size of packet buffer */
+/* Return size of header */
/* message_length Return length of message */
/* */
/* OUTPUT */
@@ -69,12 +70,22 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type,
- USHORT *header_size, UINT *message_length)
+ UINT *header_size, UINT *message_length)
{
+ /* Check buffer length. */
+ if (*header_size < 4)
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
/* The message being passed in to this function should already be stripped of the TLS header
so the first byte in the packet/record is our handshake message type. */
*message_type = packet_buffer[0];
diff --git a/nx_secure/src/nx_secure_tls_server_handshake.c b/nx_secure/src/nx_secure_tls_server_handshake.c
index 729410e2..6eb265c7 100644
--- a/nx_secure/src/nx_secure_tls_server_handshake.c
+++ b/nx_secure/src/nx_secure_tls_server_handshake.c
@@ -31,7 +31,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_server_handshake PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -99,6 +99,10 @@
/* fixed certificate buffer */
/* allocation, */
/* resulting in version 6.1 */
+/* 12-31-2020 Timothy Stapko Modified comment(s), */
+/* improved buffer length */
+/* verification, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer,
@@ -108,7 +112,7 @@ UINT _nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *
UINT status;
UINT temp_status;
USHORT message_type;
-USHORT header_bytes;
+UINT header_bytes;
UINT message_length;
NX_PACKET *send_packet;
NX_PACKET_POOL *packet_pool;
@@ -127,7 +131,14 @@ const NX_CRYPTO_METHOD *method_ptr = NX_NULL;
/* Save a pointer to the start of our packet for the hash that happens below. */
packet_start = packet_buffer;
- _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+ header_bytes = data_length;
+
+ status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
+
+ if (status != NX_SECURE_TLS_SUCCESS)
+ {
+ return(status);
+ }
/* Check for fragmented records. */
if((message_length + header_bytes) > data_length)
diff --git a/ports/cortex_m23/ac5/inc/nx_port.h b/ports/cortex_m23/ac5/inc/nx_port.h
new file mode 100644
index 00000000..34bb804d
--- /dev/null
+++ b/ports/cortex_m23/ac5/inc/nx_port.h
@@ -0,0 +1,210 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h Cortex-M23/AC5 */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) \
+ { \
+ ULONG i; \
+ ULONG tmp; \
+ i = (UINT)arg; \
+ /* i = A, B, C, D */ \
+ tmp = i ^ (((i) >> 16) | (i << 16)); \
+ /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \
+ tmp &= 0xff00ffff; \
+ /* tmp = A^C, 0, C^A, D^B */ \
+ i = ((i) >> 8) | (i<<24); \
+ /* i = D, A, B, C */ \
+ i = i ^ ((tmp) >> 8); \
+ /* i = D, C, B, A */ \
+ arg = i; \
+ }
+#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF)
+
+
+#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \
+ | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24))
+
+#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8))
+
+
+#ifndef htonl
+#define htonl(val) __SWAP32__(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __SWAP32__(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __SWAP16__(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __SWAP16__(val)
+#endif /*htons */
+
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/AC5 Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/cortex_m23/gnu/inc/nx_port.h b/ports/cortex_m23/gnu/inc/nx_port.h
new file mode 100644
index 00000000..f7b75879
--- /dev/null
+++ b/ports/cortex_m23/gnu/inc/nx_port.h
@@ -0,0 +1,199 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h Cortex-M23/GNU */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+/* By default IPv6 is enabled. */
+
+#ifndef FEATURE_NX_IPV6
+#define FEATURE_NX_IPV6
+#endif /* FEATURE_NX_IPV6 */
+
+#ifdef NX_DISABLE_IPV6
+#undef FEATURE_NX_IPV6
+#endif /* !NX_DISABLE_IPV6 */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg)
+#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg)
+
+
+#ifndef htonl
+#define htonl(val) __builtin_bswap32(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __builtin_bswap32(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __builtin_bswap16(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __builtin_bswap16(val)
+#endif /*htons */
+
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/GNU Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/cortex_m23/iar/inc/nx_port.h b/ports/cortex_m23/iar/inc/nx_port.h
new file mode 100644
index 00000000..cc714693
--- /dev/null
+++ b/ports/cortex_m23/iar/inc/nx_port.h
@@ -0,0 +1,190 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h Cortex-M23/IAR */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) arg = __REV(arg)
+#define NX_CHANGE_USHORT_ENDIAN(arg) arg = __REV16(arg)
+
+
+#ifndef htonl
+#define htonl(val) __REV(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __REV(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __REV16(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __REV16(val)
+#endif /*htons */
+
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/IAR Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/cortex_m33/ac5/inc/nx_port.h b/ports/cortex_m33/ac5/inc/nx_port.h
new file mode 100644
index 00000000..3ec61534
--- /dev/null
+++ b/ports/cortex_m33/ac5/inc/nx_port.h
@@ -0,0 +1,210 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h Cortex-M33/AC5 */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) \
+ { \
+ ULONG i; \
+ ULONG tmp; \
+ i = (UINT)arg; \
+ /* i = A, B, C, D */ \
+ tmp = i ^ (((i) >> 16) | (i << 16)); \
+ /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \
+ tmp &= 0xff00ffff; \
+ /* tmp = A^C, 0, C^A, D^B */ \
+ i = ((i) >> 8) | (i<<24); \
+ /* i = D, A, B, C */ \
+ i = i ^ ((tmp) >> 8); \
+ /* i = D, C, B, A */ \
+ arg = i; \
+ }
+#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF)
+
+
+#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \
+ | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24))
+
+#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8))
+
+
+#ifndef htonl
+#define htonl(val) __SWAP32__(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __SWAP32__(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __SWAP16__(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __SWAP16__(val)
+#endif /*htons */
+
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC5 Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/cortex_m33/gnu/inc/nx_port.h b/ports/cortex_m33/gnu/inc/nx_port.h
new file mode 100644
index 00000000..bdf29114
--- /dev/null
+++ b/ports/cortex_m33/gnu/inc/nx_port.h
@@ -0,0 +1,199 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h Cortex-M33/GNU */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+/* By default IPv6 is enabled. */
+
+#ifndef FEATURE_NX_IPV6
+#define FEATURE_NX_IPV6
+#endif /* FEATURE_NX_IPV6 */
+
+#ifdef NX_DISABLE_IPV6
+#undef FEATURE_NX_IPV6
+#endif /* !NX_DISABLE_IPV6 */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg)
+#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg)
+
+
+#ifndef htonl
+#define htonl(val) __builtin_bswap32(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __builtin_bswap32(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __builtin_bswap16(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __builtin_bswap16(val)
+#endif /*htons */
+
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/GNU Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/cortex_m33/iar/inc/nx_port.h b/ports/cortex_m33/iar/inc/nx_port.h
new file mode 100644
index 00000000..598fcbee
--- /dev/null
+++ b/ports/cortex_m33/iar/inc/nx_port.h
@@ -0,0 +1,190 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h Cortex-M33/IAR */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) arg = __REV(arg)
+#define NX_CHANGE_USHORT_ENDIAN(arg) arg = __REV16(arg)
+
+
+#ifndef htonl
+#define htonl(val) __REV(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __REV(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __REV16(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __REV16(val)
+#endif /*htons */
+
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/IAR Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/rxv2/ccrx/inc/nx_port.h b/ports/rxv2/ccrx/inc/nx_port.h
new file mode 100644
index 00000000..4f825f35
--- /dev/null
+++ b/ports/rxv2/ccrx/inc/nx_port.h
@@ -0,0 +1,221 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h RXv2/CCRX */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+/* By default IPv6 is enabled. */
+
+#ifndef FEATURE_NX_IPV6
+#define FEATURE_NX_IPV6
+#endif /* FEATURE_NX_IPV6 */
+
+#ifdef NX_DISABLE_IPV6
+#undef FEATURE_NX_IPV6
+#endif /* !NX_DISABLE_IPV6 */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) \
+ { \
+ ULONG i; \
+ ULONG tmp; \
+ i = (UINT)arg; \
+ /* i = A, B, C, D */ \
+ tmp = i ^ (((i) >> 16) | (i << 16)); \
+ /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \
+ tmp &= 0xff00ffff; \
+ /* tmp = A^C, 0, C^A, D^B */ \
+ i = ((i) >> 8) | (i<<24); \
+ /* i = D, A, B, C */ \
+ i = i ^ ((tmp) >> 8); \
+ /* i = D, C, B, A */ \
+ arg = i; \
+ }
+#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF)
+
+
+#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \
+ | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24))
+
+#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8))
+
+
+#ifndef htonl
+#define htonl(val) __SWAP32__(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __SWAP32__(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __SWAP16__(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __SWAP16__(val)
+#endif /*htons */
+
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/CCRX Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/rxv2/gnu/inc/nx_port.h b/ports/rxv2/gnu/inc/nx_port.h
new file mode 100644
index 00000000..e42bc47f
--- /dev/null
+++ b/ports/rxv2/gnu/inc/nx_port.h
@@ -0,0 +1,210 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h RXv2/GNU */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) \
+ { \
+ ULONG i; \
+ ULONG tmp; \
+ i = (UINT)arg; \
+ /* i = A, B, C, D */ \
+ tmp = i ^ (((i) >> 16) | (i << 16)); \
+ /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \
+ tmp &= 0xff00ffff; \
+ /* tmp = A^C, 0, C^A, D^B */ \
+ i = ((i) >> 8) | (i<<24); \
+ /* i = D, A, B, C */ \
+ i = i ^ ((tmp) >> 8); \
+ /* i = D, C, B, A */ \
+ arg = i; \
+ }
+#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF)
+
+
+#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \
+ | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24))
+
+#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8))
+
+
+#ifndef htonl
+#define htonl(val) __SWAP32__(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __SWAP32__(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __SWAP16__(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __SWAP16__(val)
+#endif /*htons */
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/GNU Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/rxv2/iar/inc/nx_port.h b/ports/rxv2/iar/inc/nx_port.h
new file mode 100644
index 00000000..6d2aa13f
--- /dev/null
+++ b/ports/rxv2/iar/inc/nx_port.h
@@ -0,0 +1,210 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* nx_port.h RXv2/IAR */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the NetX */
+/* real-time TCP/IP function identically on a variety of different */
+/* processor architectures. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_PORT_H
+#define NX_PORT_H
+
+/* Determine if the optional NetX user define file should be used. */
+
+#ifdef NX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in nx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "nx_user.h"
+#endif
+
+
+/* Default to little endian, since this is what most ARM targets are. */
+
+#define NX_LITTLE_ENDIAN 1
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Define various constants for the port. */
+
+#ifndef NX_IP_PERIODIC_RATE
+#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for
+ ports with 10ms timer interrupts. This
+ value may be defined instead at the
+ command line and this value will not be
+ used. */
+#endif
+
+
+/* Define macros that swap the endian for little endian ports. */
+
+#ifdef NX_LITTLE_ENDIAN
+#define NX_CHANGE_ULONG_ENDIAN(arg) \
+ { \
+ ULONG i; \
+ ULONG tmp; \
+ i = (UINT)arg; \
+ /* i = A, B, C, D */ \
+ tmp = i ^ (((i) >> 16) | (i << 16)); \
+ /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \
+ tmp &= 0xff00ffff; \
+ /* tmp = A^C, 0, C^A, D^B */ \
+ i = ((i) >> 8) | (i<<24); \
+ /* i = D, A, B, C */ \
+ i = i ^ ((tmp) >> 8); \
+ /* i = D, C, B, A */ \
+ arg = i; \
+ }
+#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF)
+
+
+#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \
+ | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24))
+
+#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8))
+
+
+#ifndef htonl
+#define htonl(val) __SWAP32__(val)
+#endif /* htonl */
+#ifndef ntohl
+#define ntohl(val) __SWAP32__(val)
+#endif /* htonl */
+
+#ifndef htons
+#define htons(val) __SWAP16__(val)
+#endif /*htons */
+
+#ifndef ntohs
+#define ntohs(val) __SWAP16__(val)
+#endif /*htons */
+
+#else
+#define NX_CHANGE_ULONG_ENDIAN(a)
+#define NX_CHANGE_USHORT_ENDIAN(a)
+
+#ifndef htons
+#define htons(val) (val)
+#endif /* htons */
+
+#ifndef ntohs
+#define ntohs(val) (val)
+#endif /* ntohs */
+
+#ifndef ntohl
+#define ntohl(val) (val)
+#endif
+
+#ifndef htonl
+#define htonl(val) (val)
+#endif /* htonl */
+#endif
+
+
+/* Define several macros for the error checking shell in NetX. */
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern TX_THREAD _tx_timer_thread; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \
+ (_tx_thread_current_ptr == &_tx_timer_thread)) \
+ return(NX_CALLER_ERROR);
+
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
+ return(NX_CALLER_ERROR);
+
+
+#else
+
+
+
+#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \
+ extern volatile ULONG _tx_thread_system_state;
+
+#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+ (_tx_thread_current_ptr == TX_NULL)) \
+ return(NX_CALLER_ERROR);
+
+#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \
+ return(NX_CALLER_ERROR);
+
+#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \
+ ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
+ return(NX_CALLER_ERROR);
+
+#endif
+
+
+/* Define the version ID of NetX. This may be utilized by the application. */
+
+#ifdef NX_SYSTEM_INIT
+CHAR _nx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/IAR Version 6.1.3 *";
+#else
+extern CHAR _nx_version_id[];
+#endif
+
+#endif
+
diff --git a/samples/demo_netx_duo_ptp_client.c b/samples/demo_netx_duo_ptp_client.c
new file mode 100644
index 00000000..cb77b07d
--- /dev/null
+++ b/samples/demo_netx_duo_ptp_client.c
@@ -0,0 +1,271 @@
+/*
+ This is a small demo of the NetX Duo PTP client on the high-performance NetX Duo TCP/IP stack.
+ This demo relies on ThreadX, NetX Duo and NetX Duo PTP client API to execute the Precision Time
+ Protocol.
+
+ */
+
+#include <stdio.h>
+#include "nx_api.h"
+#include "nxd_ptp_client.h"
+
+#ifndef SAMPLE_DHCP_DISABLE
+#include "nxd_dhcp_client.h"
+#endif /* SAMPLE_DHCP_DISABLE */
+
+#define PTP_THREAD_PRIORITY 2
+
+/* Define the ThreadX and NetX object control blocks... */
+static TX_THREAD thread_0;
+static NX_PACKET_POOL pool_0;
+static NX_IP ip_0;
+#ifndef SAMPLE_DHCP_DISABLE
+static NX_DHCP dhcp_client;
+#endif /* SAMPLE_DHCP_DISABLE */
+static NX_PTP_CLIENT ptp_client;
+
+/* Define the IP thread's stack area. */
+static ULONG ip_thread_stack[2048 / sizeof(ULONG)];
+
+/* Define packet pool for the demonstration. */
+static ULONG packet_pool_area[((1536 + sizeof(NX_PACKET)) * 32) / sizeof(ULONG)];
+
+/* Define the ARP cache area. */
+static ULONG arp_space_area[512 / sizeof(ULONG)];
+
+/* Define the main thread. */
+static ULONG thread_0_stack[2048 / sizeof(ULONG)];
+static ULONG ptp_stack[2048 / sizeof(ULONG)];
+
+/* Define an error counter. */
+static ULONG error_counter;
+
+/* Define ptp utc offset. */
+static SHORT ptp_utc_offset = 0;
+
+#ifndef SAMPLE_DHCP_DISABLE
+#define IPV4_ADDRESS IP_ADDRESS(0, 0, 0, 0)
+#define IPV4_NETWORK_MASK IP_ADDRESS(0, 0, 0, 0)
+#else
+#define IPV4_ADDRESS IP_ADDRESS(10, 1, 0, 212)
+#define IPV4_NETWORK_MASK IP_ADDRESS(255, 255, 0, 0)
+#define IPV4_GATEWAY_ADDR IP_ADDRESS(10, 1, 0, 1)
+#define DNS_SERVER_ADDRESS IP_ADDRESS(10, 1, 0, 1)
+#endif /* SAMPLE_DHCP_DISABLE */
+
+/* Define the main thread entry point. */
+static VOID thread_0_entry(ULONG thread_input);
+
+/* PTP handler. */
+static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data);
+
+#ifndef SAMPLE_DHCP_DISABLE
+static void dhcp_wait();
+#endif /* SAMPLE_DHCP_DISABLE */
+
+/***** Substitute your ethernet driver entry function here *********/
+#ifndef NETWORK_DRIVER
+#define NETWORK_DRIVER _nx_ram_network_driver
+#endif
+extern VOID NETWORK_DRIVER(NX_IP_DRIVER *driver_req_ptr);
+
+#ifndef CLOCK_CALLBACK
+#define CLOCK_CALLBACK nx_ptp_client_soft_clock_callback
+#endif
+extern UINT CLOCK_CALLBACK(NX_PTP_CLIENT *client_ptr, UINT operation,
+ NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr,
+ VOID *callback_data);
+
+#ifdef HARDWARE_SETUP
+extern VOID HARDWARE_SETUP();
+#endif
+
+int main()
+{
+#ifdef HARDWARE_SETUP
+ HARDWARE_SETUP();
+#endif
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+ return 0;
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+UINT status;
+
+
+ /* Initialize the NetX system. */
+ nx_system_initialize();
+
+ /* Create a packet pool. */
+ status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, (ULONG*)(((int)packet_pool_area + 15) & ~15) , sizeof(packet_pool_area));
+
+ /* Check for pool creation error. */
+ if (status)
+ error_counter++;
+
+ /* Create an IP instance. */
+ status = nx_ip_create(&ip_0,
+ "NetX IP Instance 0",
+ IPV4_ADDRESS,
+ IPV4_NETWORK_MASK,
+ &pool_0,
+ NETWORK_DRIVER,
+ (UCHAR*)ip_thread_stack,
+ sizeof(ip_thread_stack),
+ 1);
+
+ /* Check for IP create errors. */
+ if (status)
+ error_counter++;
+
+ /* Enable ARP and supply ARP cache memory for IP Instance 0. */
+ status = nx_arp_enable(&ip_0, (void *)arp_space_area, sizeof(arp_space_area));
+
+ /* Check for ARP enable errors. */
+ if (status)
+ error_counter++;
+
+ /* Enable TCP traffic. */
+ status = nx_tcp_enable(&ip_0);
+
+ /* Check for TCP enable errors. */
+ if (status)
+ error_counter++;
+
+ /* Enable UDP traffic. */
+ status = nx_udp_enable(&ip_0);
+
+ /* Check for UDP enable errors. */
+ if (status)
+ error_counter++;
+
+ /* Enable ICMP. */
+ status = nx_icmp_enable(&ip_0);
+
+ /* Check for errors. */
+ if (status)
+ error_counter++;
+
+ /* Create the main thread. */
+ tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
+ thread_0_stack, sizeof(thread_0_stack),
+ 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
+}
+
+
+/* Define the test threads. */
+void thread_0_entry(ULONG thread_input)
+{
+
+NX_PTP_TIME tm;
+NX_PTP_DATE_TIME date;
+
+#ifndef SAMPLE_DHCP_DISABLE
+ dhcp_wait();
+#endif /* SAMPLE_DHCP_DISABLE */
+
+ /* Create the PTP client instance */
+ nx_ptp_client_create(&ptp_client, &ip_0, 0, &pool_0,
+ PTP_THREAD_PRIORITY, (UCHAR *)ptp_stack, sizeof(ptp_stack),
+ CLOCK_CALLBACK, NX_NULL);
+
+ /* start the PTP client */
+ nx_ptp_client_start(&ptp_client, NX_NULL, 0, 0, 0, ptp_event_callback, NX_NULL);
+
+ while(1)
+ {
+
+ /* read the PTP clock */
+ nx_ptp_client_time_get(&ptp_client, &tm);
+
+ /* convert PTP time to UTC date and time */
+ nx_ptp_client_utility_convert_time_to_date(&tm, -ptp_utc_offset, &date);
+
+ /* display the current time */
+ printf("%2u/%02u/%u %02u:%02u:%02u.%09lu\r\n", date.day, date.month, date.year, date.hour, date.minute, date.second, date.nanosecond);
+
+ tx_thread_sleep(NX_IP_PERIODIC_RATE);
+ }
+}
+
+static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data)
+{
+ NX_PARAMETER_NOT_USED(callback_data);
+
+ switch (event)
+ {
+ case NX_PTP_CLIENT_EVENT_MASTER:
+ {
+ printf("new MASTER clock!\r\n");
+ break;
+ }
+
+ case NX_PTP_CLIENT_EVENT_SYNC:
+ {
+ nx_ptp_client_sync_info_get((NX_PTP_CLIENT_SYNC *)event_data, NX_NULL, &ptp_utc_offset);
+ printf("SYNC event: utc offset=%d\r\n", ptp_utc_offset);
+ break;
+ }
+
+ case NX_PTP_CLIENT_EVENT_TIMEOUT:
+ {
+ printf("Master clock TIMEOUT!\r\n");
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* DHCP */
+#ifndef SAMPLE_DHCP_DISABLE
+void dhcp_wait(void)
+{
+
+ULONG actual_status;
+ULONG ip_address;
+ULONG network_mask;
+ULONG gw_address;
+
+ printf("DHCP In Progress...\r\n");
+
+ /* Create the DHCP instance. */
+ nx_dhcp_create(&dhcp_client, &ip_0, "dhcp_client");
+
+ /* Start the DHCP Client. */
+ nx_dhcp_start(&dhcp_client);
+
+ /* Wait util address is solved. */
+ nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, NX_WAIT_FOREVER);
+
+ /* Get IP address. */
+ nx_ip_address_get(&ip_0, &ip_address, &network_mask);
+ nx_ip_gateway_address_get(&ip_0, &gw_address);
+
+ /* Output IP address. */
+ printf("IP address: %d.%d.%d.%d\r\nMask: %d.%d.%d.%d\r\nGateway: %d.%d.%d.%d\r\n",
+ (INT)(ip_address >> 24),
+ (INT)(ip_address >> 16 & 0xFF),
+ (INT)(ip_address >> 8 & 0xFF),
+ (INT)(ip_address & 0xFF),
+ (INT)(network_mask >> 24),
+ (INT)(network_mask >> 16 & 0xFF),
+ (INT)(network_mask >> 8 & 0xFF),
+ (INT)(network_mask & 0xFF),
+ (INT)(gw_address >> 24),
+ (INT)(gw_address >> 16 & 0xFF),
+ (INT)(gw_address >> 8 & 0xFF),
+ (INT)(gw_address & 0xFF));
+}
+#endif /* SAMPLE_DHCP_DISABLE */ \ No newline at end of file