Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
rte_dual_msgchannel.c
Go to the documentation of this file.
1
7
9
11
13
15
17
18
21 const rte_dual_msgchannel_config_t *config)
22{
23 if ((channel == NULL) || (config == NULL) || (config->link == NULL))
24 {
26 }
27
28 channel->link = config->link;
29 channel->sender_id = config->sender_id;
30 channel->expected_peer_id = config->expected_peer_id;
31 channel->next_sequence = 0U;
32 channel->expected_sequence = 0U;
33 channel->resync_on_sequence_error = false;
34
35 return RTE_STATUS_OK;
36}
37
39 const uint8_t *payload,
40 uint8_t payload_size,
41 rte_duration_ms_t timeout_ms,
42 uint32_t *out_sequence)
43{
45 rte_status_t status;
46
47 if (channel == NULL)
48 {
50 }
51 if ((payload == NULL) && (payload_size != 0U))
52 {
54 }
55
56 status = rte_checksum_vital_message_create(&frame, channel->sender_id, channel->next_sequence, payload,
57 (size_t)payload_size);
58 if (status != RTE_STATUS_OK)
59 {
60 return status;
61 }
62
63 status = rte_netlink_send(channel->link, &frame, sizeof(frame), timeout_ms);
64 if (status != RTE_STATUS_OK)
65 {
66 /* channel->next_sequence intentionally NOT advanced on failure -
67 * see this function's own doc: a retry reuses the same
68 * sequence_number rather than silently skipping ahead. */
69 return status;
70 }
71
72 if (out_sequence != NULL)
73 {
74 *out_sequence = channel->next_sequence;
75 }
76 channel->next_sequence++;
77
78 return RTE_STATUS_OK;
79}
80
82 uint8_t *out_payload,
83 uint8_t payload_max_size,
84 rte_duration_ms_t timeout_ms,
85 uint8_t *out_payload_size,
86 uint32_t *out_sequence)
87{
89 rte_status_t status;
90
91 if ((channel == NULL) || (out_payload == NULL) || (out_payload_size == NULL) || (payload_max_size == 0U))
92 {
94 }
95
96 status = rte_netlink_receive(channel->link, &frame, sizeof(frame), timeout_ms);
97 if (status != RTE_STATUS_OK)
98 {
99 return status;
100 }
101
102 /* Masquerade defense (ADR-020 section 1): rte_checksum_vital_message_
103 * verify() below checks CRC-64 and sequence continuity but has no
104 * concept of "which peer is this supposed to be" - that check is this
105 * layer's own responsibility. Checked before the CRC/sequence
106 * verify() call so a wrong-sender frame is reported distinctly
107 * (RTE_STATUS_HARDWARE_FAULT) rather than folded into the generic
108 * RTE_STATUS_DATA_CORRUPTION a corrupted-but-correctly-addressed
109 * frame gets. */
110 if (frame.sender_id != channel->expected_peer_id)
111 {
113 }
114
115 status = rte_checksum_vital_message_verify(&frame, channel->expected_sequence, out_payload, (size_t)payload_max_size,
116 out_payload_size);
117 if ((status == RTE_STATUS_DATA_CORRUPTION) && channel->resync_on_sequence_error &&
118 (frame.sequence_number != channel->expected_sequence))
119 {
120 rte_checksum_result_t crc_result;
121
122 if (rte_checksum_crc64_verify((const uint8_t *)&frame, sizeof(frame) - sizeof(frame.crc64), frame.crc64,
123 &crc_result) == RTE_STATUS_OK)
124 {
125 /* Intact frame from the right peer with another sequence number: the peer restarted (or we did).
126 * The frame is still rejected; only the expectation follows it. */
127 channel->expected_sequence = frame.sequence_number + 1U;
128 }
129 }
130 if (status != RTE_STATUS_OK)
131 {
132 /* channel->expected_sequence intentionally left unchanged on
133 * failure - see rte_dual_msgchannel_reset_sequence()'s own doc
134 * for the deliberate recovery path after a link (re)establishes,
135 * rather than silently resyncing here and weakening the
136 * anti-replay/anti-reorder defense this check exists for. */
137 return status;
138 }
139
140 if (out_sequence != NULL)
141 {
142 *out_sequence = frame.sequence_number;
143 }
144 channel->expected_sequence = frame.sequence_number + 1U;
145
146 return RTE_STATUS_OK;
147}
148
150{
151 if (channel == NULL)
152 {
154 }
155
156 channel->next_sequence = 0U;
157 channel->expected_sequence = 0U;
158
159 return RTE_STATUS_OK;
160}
161
163{
164 if (channel == NULL)
165 {
167 }
168 channel->resync_on_sequence_error = enable;
169 return RTE_STATUS_OK;
170}
rte_status_t rte_checksum_vital_message_verify(const rte_vital_message_t *msg, uint32_t expected_sequence, uint8_t *payload_out, size_t payload_max_size, uint8_t *payload_size_out)
Verify vital channel message and extract payload.
rte_status_t rte_checksum_vital_message_create(rte_vital_message_t *msg_out, uint32_t sender_id, uint32_t sequence, const uint8_t *payload, size_t payload_size)
Create vital channel message with CRC.
rte_status_t rte_checksum_crc64_verify(const uint8_t *data, size_t size, rte_crc64_t expected_crc, rte_checksum_result_t *result_out)
Verify CRC-64 of data against stored value.
rte_status_t rte_dual_msgchannel_receive(rte_dual_msgchannel_t *channel, uint8_t *out_payload, uint8_t payload_max_size, rte_duration_ms_t timeout_ms, uint8_t *out_payload_size, uint32_t *out_sequence)
Receives one frame over config->link, blocking at most timeout_ms, verifies its CRC-64 and sequence c...
rte_status_t rte_dual_msgchannel_reset_sequence(rte_dual_msgchannel_t *channel)
Resets both sequence counters to 0. Intended to be called by the caller (typically rte_dual_channel_t...
rte_status_t rte_dual_msgchannel_init(rte_dual_msgchannel_t *channel, const rte_dual_msgchannel_config_t *config)
Initializes a rte_dual_msgchannel_t: starts both sequence counters at 0.
rte_status_t rte_dual_msgchannel_set_resync_on_sequence_error(rte_dual_msgchannel_t *channel, bool enable)
Turns sequence resynchronisation on or off (default off after init).
rte_status_t rte_dual_msgchannel_send(rte_dual_msgchannel_t *channel, const uint8_t *payload, uint8_t payload_size, rte_duration_ms_t timeout_ms, uint32_t *out_sequence)
Wraps payload in a rte_vital_message_t (this channel's own sender_id and next sequence_number) and se...
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_INVALID_PARAM
Definition rte_status.h:29
@ RTE_STATUS_DATA_CORRUPTION
Definition rte_status.h:37
@ RTE_STATUS_HARDWARE_FAULT
Definition rte_status.h:36
uint32_t rte_duration_ms_t
Definition rte_types.h:27
"Channel" layer of ADR-020: one EN 50159-defended message channel over one already-open rte_netlink_h...
Checksum result for validation.
Configuration for rte_dual_msgchannel_init().
One rte_dual_msgchannel_t instance's state. Caller-owned storage (REQ-DUAL-MSGCHANNEL-001); opaque in...
rte_netlink_handle_t link
Vital channel message with integrated CRC-64.