1*479e2648SJackson Cooper-Driver /*
2*479e2648SJackson Cooper-Driver * Copyright (c) 2026, Arm Limited. All rights reserved.
3*479e2648SJackson Cooper-Driver *
4*479e2648SJackson Cooper-Driver * SPDX-License-Identifier: BSD-3-Clause
5*479e2648SJackson Cooper-Driver *
6*479e2648SJackson Cooper-Driver */
7*479e2648SJackson Cooper-Driver
8*479e2648SJackson Cooper-Driver #include <assert.h>
9*479e2648SJackson Cooper-Driver #include <string.h>
10*479e2648SJackson Cooper-Driver
11*479e2648SJackson Cooper-Driver #include <drivers/arm/sfcp.h>
12*479e2648SJackson Cooper-Driver #include "sfcp_defs.h"
13*479e2648SJackson Cooper-Driver #include "sfcp_encryption.h"
14*479e2648SJackson Cooper-Driver #include "sfcp_handler_buffer.h"
15*479e2648SJackson Cooper-Driver #include "sfcp_helpers.h"
16*479e2648SJackson Cooper-Driver #include "sfcp_link_hal.h"
17*479e2648SJackson Cooper-Driver #include "sfcp_protocol_error.h"
18*479e2648SJackson Cooper-Driver #include "sfcp_random.h"
19*479e2648SJackson Cooper-Driver
20*479e2648SJackson Cooper-Driver #include <platform_def.h>
21*479e2648SJackson Cooper-Driver
22*479e2648SJackson Cooper-Driver #ifndef SFCP_MAX_NUMBER_MESSAGE_HANDLERS
23*479e2648SJackson Cooper-Driver #define SFCP_MAX_NUMBER_MESSAGE_HANDLERS (2)
24*479e2648SJackson Cooper-Driver #endif
25*479e2648SJackson Cooper-Driver
26*479e2648SJackson Cooper-Driver #ifndef SFCP_MAX_NUMBER_REPLY_HANDLERS
27*479e2648SJackson Cooper-Driver #define SFCP_MAX_NUMBER_REPLY_HANDLERS (2)
28*479e2648SJackson Cooper-Driver #endif
29*479e2648SJackson Cooper-Driver
30*479e2648SJackson Cooper-Driver #define BUS_ARBITRATION_RANDOM_DELAY_MAX_CYCLES (10000)
31*479e2648SJackson Cooper-Driver
32*479e2648SJackson Cooper-Driver struct sfcp_handler_table_entry_t {
33*479e2648SJackson Cooper-Driver sfcp_handler_t handler;
34*479e2648SJackson Cooper-Driver union {
35*479e2648SJackson Cooper-Driver uint16_t application_id;
36*479e2648SJackson Cooper-Driver uint16_t client_id;
37*479e2648SJackson Cooper-Driver };
38*479e2648SJackson Cooper-Driver bool in_use;
39*479e2648SJackson Cooper-Driver };
40*479e2648SJackson Cooper-Driver
41*479e2648SJackson Cooper-Driver static struct sfcp_handler_table_entry_t
42*479e2648SJackson Cooper-Driver sfcp_msg_handlers[SFCP_MAX_NUMBER_MESSAGE_HANDLERS];
43*479e2648SJackson Cooper-Driver static struct sfcp_handler_table_entry_t
44*479e2648SJackson Cooper-Driver sfcp_reply_handlers[SFCP_MAX_NUMBER_REPLY_HANDLERS];
45*479e2648SJackson Cooper-Driver
46*479e2648SJackson Cooper-Driver struct sfcp_requires_handshake_t {
47*479e2648SJackson Cooper-Driver bool requires_handshake;
48*479e2648SJackson Cooper-Driver uint8_t trusted_subnet_id;
49*479e2648SJackson Cooper-Driver };
50*479e2648SJackson Cooper-Driver
51*479e2648SJackson Cooper-Driver static struct sfcp_requires_handshake_t sfcp_requires_handshake;
52*479e2648SJackson Cooper-Driver
53*479e2648SJackson Cooper-Driver static inline enum sfcp_error_t
sfcp_protocol_error_to_sfcp_error(enum sfcp_protocol_error_t protocol_error)54*479e2648SJackson Cooper-Driver sfcp_protocol_error_to_sfcp_error(enum sfcp_protocol_error_t protocol_error)
55*479e2648SJackson Cooper-Driver {
56*479e2648SJackson Cooper-Driver switch (protocol_error) {
57*479e2648SJackson Cooper-Driver case SFCP_PROTOCOL_ERROR_TRY_AGAIN_LATER:
58*479e2648SJackson Cooper-Driver return SFCP_ERROR_SEND_MSG_AGAIN;
59*479e2648SJackson Cooper-Driver default:
60*479e2648SJackson Cooper-Driver return SFCP_ERROR_PROTOCOL_ERROR;
61*479e2648SJackson Cooper-Driver }
62*479e2648SJackson Cooper-Driver }
63*479e2648SJackson Cooper-Driver
64*479e2648SJackson Cooper-Driver static inline void
populate_reply_metadata(struct sfcp_reply_metadata_t * metadata,sfcp_node_id_t receiver,bool uses_cryptography,uint16_t client_id,uint16_t application_id,uint8_t message_id,uint8_t trusted_subnet_id)65*479e2648SJackson Cooper-Driver populate_reply_metadata(struct sfcp_reply_metadata_t *metadata,
66*479e2648SJackson Cooper-Driver sfcp_node_id_t receiver, bool uses_cryptography,
67*479e2648SJackson Cooper-Driver uint16_t client_id, uint16_t application_id,
68*479e2648SJackson Cooper-Driver uint8_t message_id, uint8_t trusted_subnet_id)
69*479e2648SJackson Cooper-Driver {
70*479e2648SJackson Cooper-Driver metadata->receiver = receiver;
71*479e2648SJackson Cooper-Driver metadata->uses_cryptography = uses_cryptography;
72*479e2648SJackson Cooper-Driver metadata->trusted_subnet_id = trusted_subnet_id;
73*479e2648SJackson Cooper-Driver metadata->client_id = client_id;
74*479e2648SJackson Cooper-Driver metadata->application_id = application_id;
75*479e2648SJackson Cooper-Driver metadata->message_id = message_id;
76*479e2648SJackson Cooper-Driver }
77*479e2648SJackson Cooper-Driver
78*479e2648SJackson Cooper-Driver static inline void
populate_msg_metadata(struct sfcp_msg_metadata_t * metadata,sfcp_node_id_t sender,bool uses_cryptography,uint16_t client_id,uint16_t application_id,uint8_t message_id,uint8_t trusted_subnet_id)79*479e2648SJackson Cooper-Driver populate_msg_metadata(struct sfcp_msg_metadata_t *metadata,
80*479e2648SJackson Cooper-Driver sfcp_node_id_t sender, bool uses_cryptography,
81*479e2648SJackson Cooper-Driver uint16_t client_id, uint16_t application_id,
82*479e2648SJackson Cooper-Driver uint8_t message_id, uint8_t trusted_subnet_id)
83*479e2648SJackson Cooper-Driver {
84*479e2648SJackson Cooper-Driver metadata->sender = sender;
85*479e2648SJackson Cooper-Driver metadata->uses_cryptography = uses_cryptography;
86*479e2648SJackson Cooper-Driver metadata->trusted_subnet_id = trusted_subnet_id;
87*479e2648SJackson Cooper-Driver metadata->client_id = client_id;
88*479e2648SJackson Cooper-Driver metadata->application_id = application_id;
89*479e2648SJackson Cooper-Driver metadata->message_id = message_id;
90*479e2648SJackson Cooper-Driver }
91*479e2648SJackson Cooper-Driver
sfcp_init(void)92*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_init(void)
93*479e2648SJackson Cooper-Driver {
94*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
95*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
96*479e2648SJackson Cooper-Driver
97*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_init();
98*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
99*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
100*479e2648SJackson Cooper-Driver }
101*479e2648SJackson Cooper-Driver
102*479e2648SJackson Cooper-Driver sfcp_err = sfcp_trusted_subnet_state_init();
103*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
104*479e2648SJackson Cooper-Driver return sfcp_err;
105*479e2648SJackson Cooper-Driver }
106*479e2648SJackson Cooper-Driver
107*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
108*479e2648SJackson Cooper-Driver }
109*479e2648SJackson Cooper-Driver
get_new_message_id(sfcp_node_id_t node)110*479e2648SJackson Cooper-Driver static uint8_t get_new_message_id(sfcp_node_id_t node)
111*479e2648SJackson Cooper-Driver {
112*479e2648SJackson Cooper-Driver static uint8_t message_ids_per_node[SFCP_NUMBER_NODES];
113*479e2648SJackson Cooper-Driver
114*479e2648SJackson Cooper-Driver return message_ids_per_node[node]++;
115*479e2648SJackson Cooper-Driver }
116*479e2648SJackson Cooper-Driver
sfcp_init_msg(uint8_t * buf,size_t buf_size,sfcp_node_id_t receiver,uint16_t application_id,uint16_t client_id,bool needs_reply,bool manually_specify_ts_id,uint8_t trusted_subnet_id,uint8_t ** payload,size_t * payload_len,struct sfcp_packet_t ** msg,size_t * msg_size,struct sfcp_reply_metadata_t * metadata)117*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_init_msg(uint8_t *buf, size_t buf_size,
118*479e2648SJackson Cooper-Driver sfcp_node_id_t receiver,
119*479e2648SJackson Cooper-Driver uint16_t application_id, uint16_t client_id,
120*479e2648SJackson Cooper-Driver bool needs_reply, bool manually_specify_ts_id,
121*479e2648SJackson Cooper-Driver uint8_t trusted_subnet_id, uint8_t **payload,
122*479e2648SJackson Cooper-Driver size_t *payload_len, struct sfcp_packet_t **msg,
123*479e2648SJackson Cooper-Driver size_t *msg_size,
124*479e2648SJackson Cooper-Driver struct sfcp_reply_metadata_t *metadata)
125*479e2648SJackson Cooper-Driver {
126*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
127*479e2648SJackson Cooper-Driver bool uses_id_extension;
128*479e2648SJackson Cooper-Driver struct sfcp_packet_t *msg_ptr;
129*479e2648SJackson Cooper-Driver sfcp_node_id_t my_node_id;
130*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
131*479e2648SJackson Cooper-Driver uint8_t message_id;
132*479e2648SJackson Cooper-Driver struct sfcp_trusted_subnet_config_t *trusted_subnet;
133*479e2648SJackson Cooper-Driver bool found_trusted_subnet = false;
134*479e2648SJackson Cooper-Driver bool uses_cryptography;
135*479e2648SJackson Cooper-Driver
136*479e2648SJackson Cooper-Driver if ((buf == NULL) || (payload == NULL) || (payload_len == NULL) ||
137*479e2648SJackson Cooper-Driver (msg == NULL) || (msg_size == NULL) || (metadata == NULL)) {
138*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
139*479e2648SJackson Cooper-Driver }
140*479e2648SJackson Cooper-Driver
141*479e2648SJackson Cooper-Driver uses_id_extension = (application_id != 0) || (client_id != 0);
142*479e2648SJackson Cooper-Driver
143*479e2648SJackson Cooper-Driver if (manually_specify_ts_id) {
144*479e2648SJackson Cooper-Driver sfcp_err = sfcp_get_trusted_subnet_by_id(trusted_subnet_id,
145*479e2648SJackson Cooper-Driver &trusted_subnet);
146*479e2648SJackson Cooper-Driver if (sfcp_err == SFCP_ERROR_SUCCESS) {
147*479e2648SJackson Cooper-Driver found_trusted_subnet = true;
148*479e2648SJackson Cooper-Driver } else {
149*479e2648SJackson Cooper-Driver return sfcp_err;
150*479e2648SJackson Cooper-Driver }
151*479e2648SJackson Cooper-Driver } else {
152*479e2648SJackson Cooper-Driver if (trusted_subnet_id != 0) {
153*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_TRUSTED_SUBNET_ID;
154*479e2648SJackson Cooper-Driver }
155*479e2648SJackson Cooper-Driver
156*479e2648SJackson Cooper-Driver sfcp_err = sfcp_get_trusted_subnet_for_node(receiver,
157*479e2648SJackson Cooper-Driver &trusted_subnet);
158*479e2648SJackson Cooper-Driver if (sfcp_err == SFCP_ERROR_SUCCESS) {
159*479e2648SJackson Cooper-Driver found_trusted_subnet = true;
160*479e2648SJackson Cooper-Driver }
161*479e2648SJackson Cooper-Driver }
162*479e2648SJackson Cooper-Driver
163*479e2648SJackson Cooper-Driver if (found_trusted_subnet) {
164*479e2648SJackson Cooper-Driver sfcp_err =
165*479e2648SJackson Cooper-Driver sfcp_trusted_subnet_state_requires_handshake_encryption(
166*479e2648SJackson Cooper-Driver trusted_subnet->id,
167*479e2648SJackson Cooper-Driver &sfcp_requires_handshake.requires_handshake,
168*479e2648SJackson Cooper-Driver &uses_cryptography);
169*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
170*479e2648SJackson Cooper-Driver return sfcp_err;
171*479e2648SJackson Cooper-Driver }
172*479e2648SJackson Cooper-Driver
173*479e2648SJackson Cooper-Driver if (sfcp_requires_handshake.requires_handshake) {
174*479e2648SJackson Cooper-Driver sfcp_requires_handshake.trusted_subnet_id =
175*479e2648SJackson Cooper-Driver trusted_subnet->id;
176*479e2648SJackson Cooper-Driver }
177*479e2648SJackson Cooper-Driver } else {
178*479e2648SJackson Cooper-Driver uses_cryptography = false;
179*479e2648SJackson Cooper-Driver }
180*479e2648SJackson Cooper-Driver
181*479e2648SJackson Cooper-Driver if (buf_size < SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(uses_cryptography,
182*479e2648SJackson Cooper-Driver uses_id_extension)) {
183*479e2648SJackson Cooper-Driver return SFCP_ERROR_BUFFER_TOO_SMALL;
184*479e2648SJackson Cooper-Driver }
185*479e2648SJackson Cooper-Driver
186*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_get_my_node_id(&my_node_id);
187*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
188*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
189*479e2648SJackson Cooper-Driver }
190*479e2648SJackson Cooper-Driver
191*479e2648SJackson Cooper-Driver if ((receiver >= SFCP_NUMBER_NODES) || (receiver == my_node_id)) {
192*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
193*479e2648SJackson Cooper-Driver }
194*479e2648SJackson Cooper-Driver
195*479e2648SJackson Cooper-Driver msg_ptr = (struct sfcp_packet_t *)buf;
196*479e2648SJackson Cooper-Driver message_id = get_new_message_id(receiver);
197*479e2648SJackson Cooper-Driver
198*479e2648SJackson Cooper-Driver msg_ptr->header.metadata = SET_ALL_METADATA_FIELDS(
199*479e2648SJackson Cooper-Driver needs_reply ? SFCP_PACKET_TYPE_MSG_NEEDS_REPLY :
200*479e2648SJackson Cooper-Driver SFCP_PACKET_TYPE_MSG_NO_REPLY,
201*479e2648SJackson Cooper-Driver uses_cryptography, uses_id_extension, SFCP_PROTOCOL_VERSION);
202*479e2648SJackson Cooper-Driver msg_ptr->header.receiver_id = receiver;
203*479e2648SJackson Cooper-Driver msg_ptr->header.sender_id = my_node_id;
204*479e2648SJackson Cooper-Driver msg_ptr->header.message_id = message_id;
205*479e2648SJackson Cooper-Driver
206*479e2648SJackson Cooper-Driver if (uses_id_extension) {
207*479e2648SJackson Cooper-Driver GET_SFCP_CLIENT_ID(msg_ptr, uses_cryptography) = client_id;
208*479e2648SJackson Cooper-Driver GET_SFCP_APPLICATION_ID(msg_ptr, uses_cryptography) =
209*479e2648SJackson Cooper-Driver application_id;
210*479e2648SJackson Cooper-Driver }
211*479e2648SJackson Cooper-Driver
212*479e2648SJackson Cooper-Driver if (uses_cryptography) {
213*479e2648SJackson Cooper-Driver struct sfcp_cryptography_metadata_t *crypto_metadata =
214*479e2648SJackson Cooper-Driver &msg_ptr->cryptography_used.cryptography_metadata;
215*479e2648SJackson Cooper-Driver
216*479e2648SJackson Cooper-Driver crypto_metadata->config.trusted_subnet_id = trusted_subnet->id;
217*479e2648SJackson Cooper-Driver }
218*479e2648SJackson Cooper-Driver
219*479e2648SJackson Cooper-Driver *payload = (uint8_t *)GET_SFCP_PAYLOAD_PTR(msg_ptr, uses_cryptography,
220*479e2648SJackson Cooper-Driver uses_id_extension);
221*479e2648SJackson Cooper-Driver *payload_len = buf_size - SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(
222*479e2648SJackson Cooper-Driver uses_cryptography, uses_id_extension);
223*479e2648SJackson Cooper-Driver
224*479e2648SJackson Cooper-Driver *msg = msg_ptr;
225*479e2648SJackson Cooper-Driver *msg_size = buf_size;
226*479e2648SJackson Cooper-Driver
227*479e2648SJackson Cooper-Driver populate_reply_metadata(metadata, receiver, uses_cryptography,
228*479e2648SJackson Cooper-Driver client_id, application_id, message_id,
229*479e2648SJackson Cooper-Driver trusted_subnet_id);
230*479e2648SJackson Cooper-Driver
231*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
232*479e2648SJackson Cooper-Driver }
233*479e2648SJackson Cooper-Driver
__send_msg_reply(sfcp_node_id_t remote_node,sfcp_link_id_t link_id,struct sfcp_packet_t * packet,size_t packet_size,bool is_msg)234*479e2648SJackson Cooper-Driver static enum sfcp_error_t __send_msg_reply(sfcp_node_id_t remote_node,
235*479e2648SJackson Cooper-Driver sfcp_link_id_t link_id,
236*479e2648SJackson Cooper-Driver struct sfcp_packet_t *packet,
237*479e2648SJackson Cooper-Driver size_t packet_size, bool is_msg)
238*479e2648SJackson Cooper-Driver {
239*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
240*479e2648SJackson Cooper-Driver volatile uint64_t lfsr_random;
241*479e2648SJackson Cooper-Driver
242*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_send_message(link_id, (const uint8_t *)packet,
243*479e2648SJackson Cooper-Driver packet_size);
244*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SEND_MESSAGE_BUS_BUSY) {
245*479e2648SJackson Cooper-Driver /* Success or error we cannot handle
246*479e2648SJackson Cooper-Driver * here
247*479e2648SJackson Cooper-Driver */
248*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
249*479e2648SJackson Cooper-Driver }
250*479e2648SJackson Cooper-Driver
251*479e2648SJackson Cooper-Driver /* Wait arbitrary amount of time
252*479e2648SJackson Cooper-Driver * before returning to ensure bus arbitration.
253*479e2648SJackson Cooper-Driver * Seed the LFSR with the packet
254*479e2648SJackson Cooper-Driver */
255*479e2648SJackson Cooper-Driver lfsr_random = sfcp_random_generate_random_lfsr((uint8_t *)packet,
256*479e2648SJackson Cooper-Driver packet_size) %
257*479e2648SJackson Cooper-Driver BUS_ARBITRATION_RANDOM_DELAY_MAX_CYCLES;
258*479e2648SJackson Cooper-Driver
259*479e2648SJackson Cooper-Driver while (lfsr_random > 0) {
260*479e2648SJackson Cooper-Driver lfsr_random--;
261*479e2648SJackson Cooper-Driver }
262*479e2648SJackson Cooper-Driver
263*479e2648SJackson Cooper-Driver /* Indicate to the caller that a message is
264*479e2648SJackson Cooper-Driver * waiting, we expect the caller to receive the
265*479e2648SJackson Cooper-Driver * pending message or wait before trying to
266*479e2648SJackson Cooper-Driver * send their message again
267*479e2648SJackson Cooper-Driver */
268*479e2648SJackson Cooper-Driver return SFCP_ERROR_SEND_MSG_BUS_BUSY;
269*479e2648SJackson Cooper-Driver }
270*479e2648SJackson Cooper-Driver
send_msg_reply(struct sfcp_packet_t * packet,size_t packet_size,size_t payload_size,bool is_msg)271*479e2648SJackson Cooper-Driver static enum sfcp_error_t send_msg_reply(struct sfcp_packet_t *packet,
272*479e2648SJackson Cooper-Driver size_t packet_size, size_t payload_size,
273*479e2648SJackson Cooper-Driver bool is_msg)
274*479e2648SJackson Cooper-Driver {
275*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
276*479e2648SJackson Cooper-Driver bool uses_cryptography, uses_id_extension;
277*479e2648SJackson Cooper-Driver sfcp_link_id_t link_id;
278*479e2648SJackson Cooper-Driver size_t packet_transfer_size;
279*479e2648SJackson Cooper-Driver sfcp_node_id_t remote_node;
280*479e2648SJackson Cooper-Driver
281*479e2648SJackson Cooper-Driver if (packet == NULL) {
282*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_PACKET;
283*479e2648SJackson Cooper-Driver }
284*479e2648SJackson Cooper-Driver
285*479e2648SJackson Cooper-Driver if (packet_size < sizeof(struct sfcp_header_t)) {
286*479e2648SJackson Cooper-Driver return SFCP_ERROR_MESSAGE_TOO_SMALL;
287*479e2648SJackson Cooper-Driver }
288*479e2648SJackson Cooper-Driver
289*479e2648SJackson Cooper-Driver uses_cryptography =
290*479e2648SJackson Cooper-Driver GET_METADATA_FIELD(USES_CRYPTOGRAPHY, packet->header.metadata);
291*479e2648SJackson Cooper-Driver uses_id_extension =
292*479e2648SJackson Cooper-Driver GET_METADATA_FIELD(USES_ID_EXTENSION, packet->header.metadata);
293*479e2648SJackson Cooper-Driver remote_node = is_msg ? packet->header.receiver_id :
294*479e2648SJackson Cooper-Driver packet->header.sender_id;
295*479e2648SJackson Cooper-Driver
296*479e2648SJackson Cooper-Driver if (packet_size < SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(uses_cryptography,
297*479e2648SJackson Cooper-Driver uses_id_extension)) {
298*479e2648SJackson Cooper-Driver return SFCP_ERROR_MESSAGE_TOO_SMALL;
299*479e2648SJackson Cooper-Driver }
300*479e2648SJackson Cooper-Driver
301*479e2648SJackson Cooper-Driver if (payload_size >
302*479e2648SJackson Cooper-Driver (packet_size - SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(
303*479e2648SJackson Cooper-Driver uses_cryptography, uses_id_extension))) {
304*479e2648SJackson Cooper-Driver return SFCP_ERROR_PAYLOAD_TOO_LARGE;
305*479e2648SJackson Cooper-Driver }
306*479e2648SJackson Cooper-Driver
307*479e2648SJackson Cooper-Driver packet_transfer_size = SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(
308*479e2648SJackson Cooper-Driver uses_cryptography, uses_id_extension) +
309*479e2648SJackson Cooper-Driver payload_size;
310*479e2648SJackson Cooper-Driver
311*479e2648SJackson Cooper-Driver if (uses_cryptography) {
312*479e2648SJackson Cooper-Driver if (is_msg) {
313*479e2648SJackson Cooper-Driver sfcp_err = sfcp_encrypt_msg(
314*479e2648SJackson Cooper-Driver packet, packet_transfer_size,
315*479e2648SJackson Cooper-Driver packet->cryptography_used.cryptography_metadata
316*479e2648SJackson Cooper-Driver .config.trusted_subnet_id,
317*479e2648SJackson Cooper-Driver remote_node);
318*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
319*479e2648SJackson Cooper-Driver return sfcp_err;
320*479e2648SJackson Cooper-Driver }
321*479e2648SJackson Cooper-Driver } else {
322*479e2648SJackson Cooper-Driver sfcp_err = sfcp_encrypt_reply(
323*479e2648SJackson Cooper-Driver packet, packet_transfer_size,
324*479e2648SJackson Cooper-Driver packet->cryptography_used.cryptography_metadata
325*479e2648SJackson Cooper-Driver .config.trusted_subnet_id,
326*479e2648SJackson Cooper-Driver remote_node);
327*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
328*479e2648SJackson Cooper-Driver return sfcp_err;
329*479e2648SJackson Cooper-Driver }
330*479e2648SJackson Cooper-Driver }
331*479e2648SJackson Cooper-Driver }
332*479e2648SJackson Cooper-Driver
333*479e2648SJackson Cooper-Driver link_id = sfcp_hal_get_route(remote_node);
334*479e2648SJackson Cooper-Driver if (link_id == 0) {
335*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
336*479e2648SJackson Cooper-Driver }
337*479e2648SJackson Cooper-Driver
338*479e2648SJackson Cooper-Driver #ifdef SFCP_SUPPORT_LEGACY_MSG_PROTOCOL
339*479e2648SJackson Cooper-Driver if (is_msg) {
340*479e2648SJackson Cooper-Driver sfcp_err = sfcp_convert_to_legacy_msg(
341*479e2648SJackson Cooper-Driver (uint8_t *)packet, packet_transfer_size,
342*479e2648SJackson Cooper-Driver sfcp_legacy_conversion_buffer,
343*479e2648SJackson Cooper-Driver sizeof(sfcp_legacy_conversion_buffer),
344*479e2648SJackson Cooper-Driver &packet_transfer_size);
345*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
346*479e2648SJackson Cooper-Driver return sfcp_err;
347*479e2648SJackson Cooper-Driver }
348*479e2648SJackson Cooper-Driver } else {
349*479e2648SJackson Cooper-Driver sfcp_err = sfcp_convert_to_legacy_reply(
350*479e2648SJackson Cooper-Driver (uint8_t *)packet, packet_transfer_size,
351*479e2648SJackson Cooper-Driver sfcp_legacy_conversion_buffer,
352*479e2648SJackson Cooper-Driver sizeof(sfcp_legacy_conversion_buffer),
353*479e2648SJackson Cooper-Driver &packet_transfer_size);
354*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
355*479e2648SJackson Cooper-Driver return sfcp_err;
356*479e2648SJackson Cooper-Driver }
357*479e2648SJackson Cooper-Driver }
358*479e2648SJackson Cooper-Driver
359*479e2648SJackson Cooper-Driver packet = (struct sfcp_packet_t *)sfcp_legacy_conversion_buffer;
360*479e2648SJackson Cooper-Driver #endif
361*479e2648SJackson Cooper-Driver
362*479e2648SJackson Cooper-Driver return __send_msg_reply(remote_node, link_id, packet,
363*479e2648SJackson Cooper-Driver packet_transfer_size, is_msg);
364*479e2648SJackson Cooper-Driver }
365*479e2648SJackson Cooper-Driver
sfcp_send_msg(struct sfcp_packet_t * msg,size_t msg_size,size_t payload_size)366*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_send_msg(struct sfcp_packet_t *msg, size_t msg_size,
367*479e2648SJackson Cooper-Driver size_t payload_size)
368*479e2648SJackson Cooper-Driver {
369*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
370*479e2648SJackson Cooper-Driver
371*479e2648SJackson Cooper-Driver if (sfcp_requires_handshake.requires_handshake) {
372*479e2648SJackson Cooper-Driver sfcp_err = sfcp_encryption_handshake_initiator(
373*479e2648SJackson Cooper-Driver sfcp_requires_handshake.trusted_subnet_id, true);
374*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
375*479e2648SJackson Cooper-Driver return sfcp_err;
376*479e2648SJackson Cooper-Driver }
377*479e2648SJackson Cooper-Driver }
378*479e2648SJackson Cooper-Driver
379*479e2648SJackson Cooper-Driver return send_msg_reply(msg, msg_size, payload_size, true);
380*479e2648SJackson Cooper-Driver }
381*479e2648SJackson Cooper-Driver
sfcp_init_reply(uint8_t * buf,size_t buf_size,struct sfcp_msg_metadata_t metadata,uint8_t ** payload,size_t * payload_len,struct sfcp_packet_t ** reply,size_t * reply_size)382*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_init_reply(uint8_t *buf, size_t buf_size,
383*479e2648SJackson Cooper-Driver struct sfcp_msg_metadata_t metadata,
384*479e2648SJackson Cooper-Driver uint8_t **payload, size_t *payload_len,
385*479e2648SJackson Cooper-Driver struct sfcp_packet_t **reply,
386*479e2648SJackson Cooper-Driver size_t *reply_size)
387*479e2648SJackson Cooper-Driver {
388*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
389*479e2648SJackson Cooper-Driver struct sfcp_packet_t *reply_ptr;
390*479e2648SJackson Cooper-Driver bool uses_id_extension, uses_cryptography;
391*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
392*479e2648SJackson Cooper-Driver sfcp_node_id_t my_node_id;
393*479e2648SJackson Cooper-Driver struct sfcp_trusted_subnet_config_t *trusted_subnet;
394*479e2648SJackson Cooper-Driver
395*479e2648SJackson Cooper-Driver if ((buf == NULL) || (payload == NULL) || (payload_len == NULL) ||
396*479e2648SJackson Cooper-Driver (reply == NULL) || (reply_size == NULL)) {
397*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
398*479e2648SJackson Cooper-Driver }
399*479e2648SJackson Cooper-Driver
400*479e2648SJackson Cooper-Driver uses_id_extension = (metadata.client_id != 0) ||
401*479e2648SJackson Cooper-Driver (metadata.application_id != 0);
402*479e2648SJackson Cooper-Driver uses_cryptography = metadata.uses_cryptography;
403*479e2648SJackson Cooper-Driver
404*479e2648SJackson Cooper-Driver if (buf_size < SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(uses_cryptography,
405*479e2648SJackson Cooper-Driver uses_id_extension)) {
406*479e2648SJackson Cooper-Driver return SFCP_ERROR_BUFFER_TOO_SMALL;
407*479e2648SJackson Cooper-Driver }
408*479e2648SJackson Cooper-Driver
409*479e2648SJackson Cooper-Driver if (uses_cryptography) {
410*479e2648SJackson Cooper-Driver sfcp_err = sfcp_get_trusted_subnet_by_id(
411*479e2648SJackson Cooper-Driver metadata.trusted_subnet_id, &trusted_subnet);
412*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
413*479e2648SJackson Cooper-Driver return sfcp_err;
414*479e2648SJackson Cooper-Driver }
415*479e2648SJackson Cooper-Driver }
416*479e2648SJackson Cooper-Driver
417*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_get_my_node_id(&my_node_id);
418*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
419*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
420*479e2648SJackson Cooper-Driver }
421*479e2648SJackson Cooper-Driver
422*479e2648SJackson Cooper-Driver reply_ptr = (struct sfcp_packet_t *)buf;
423*479e2648SJackson Cooper-Driver
424*479e2648SJackson Cooper-Driver reply_ptr->header.metadata = SET_ALL_METADATA_FIELDS(
425*479e2648SJackson Cooper-Driver SFCP_PACKET_TYPE_REPLY, uses_cryptography, uses_id_extension,
426*479e2648SJackson Cooper-Driver SFCP_PROTOCOL_VERSION);
427*479e2648SJackson Cooper-Driver reply_ptr->header.receiver_id = my_node_id;
428*479e2648SJackson Cooper-Driver reply_ptr->header.sender_id = metadata.sender;
429*479e2648SJackson Cooper-Driver reply_ptr->header.message_id = metadata.message_id;
430*479e2648SJackson Cooper-Driver
431*479e2648SJackson Cooper-Driver if (uses_id_extension) {
432*479e2648SJackson Cooper-Driver GET_SFCP_CLIENT_ID(reply_ptr, uses_cryptography) =
433*479e2648SJackson Cooper-Driver metadata.client_id;
434*479e2648SJackson Cooper-Driver GET_SFCP_APPLICATION_ID(reply_ptr, uses_cryptography) =
435*479e2648SJackson Cooper-Driver metadata.application_id;
436*479e2648SJackson Cooper-Driver }
437*479e2648SJackson Cooper-Driver
438*479e2648SJackson Cooper-Driver if (uses_cryptography) {
439*479e2648SJackson Cooper-Driver struct sfcp_cryptography_metadata_t *crypto_metadata =
440*479e2648SJackson Cooper-Driver &reply_ptr->cryptography_used.cryptography_metadata;
441*479e2648SJackson Cooper-Driver
442*479e2648SJackson Cooper-Driver crypto_metadata->config.trusted_subnet_id = trusted_subnet->id;
443*479e2648SJackson Cooper-Driver }
444*479e2648SJackson Cooper-Driver
445*479e2648SJackson Cooper-Driver *payload = (uint8_t *)GET_SFCP_PAYLOAD_PTR(reply_ptr, uses_cryptography,
446*479e2648SJackson Cooper-Driver uses_id_extension);
447*479e2648SJackson Cooper-Driver *payload_len = buf_size - SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(
448*479e2648SJackson Cooper-Driver uses_cryptography, uses_id_extension);
449*479e2648SJackson Cooper-Driver
450*479e2648SJackson Cooper-Driver *reply = reply_ptr;
451*479e2648SJackson Cooper-Driver *reply_size = buf_size;
452*479e2648SJackson Cooper-Driver
453*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
454*479e2648SJackson Cooper-Driver }
455*479e2648SJackson Cooper-Driver
sfcp_send_reply(struct sfcp_packet_t * reply,size_t reply_size,size_t payload_size)456*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_send_reply(struct sfcp_packet_t *reply,
457*479e2648SJackson Cooper-Driver size_t reply_size, size_t payload_size)
458*479e2648SJackson Cooper-Driver {
459*479e2648SJackson Cooper-Driver return send_msg_reply(reply, reply_size, payload_size, false);
460*479e2648SJackson Cooper-Driver }
461*479e2648SJackson Cooper-Driver
462*479e2648SJackson Cooper-Driver static enum sfcp_error_t
send_protocol_error(sfcp_node_id_t sender_id,sfcp_node_id_t receiver_id,sfcp_link_id_t link_id,uint16_t client_id,uint8_t message_id,enum sfcp_protocol_error_t error)463*479e2648SJackson Cooper-Driver send_protocol_error(sfcp_node_id_t sender_id, sfcp_node_id_t receiver_id,
464*479e2648SJackson Cooper-Driver sfcp_link_id_t link_id, uint16_t client_id,
465*479e2648SJackson Cooper-Driver uint8_t message_id, enum sfcp_protocol_error_t error)
466*479e2648SJackson Cooper-Driver {
467*479e2648SJackson Cooper-Driver struct sfcp_packet_t packet;
468*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
469*479e2648SJackson Cooper-Driver
470*479e2648SJackson Cooper-Driver sfcp_helpers_generate_protocol_error_packet(&packet, sender_id,
471*479e2648SJackson Cooper-Driver receiver_id, link_id,
472*479e2648SJackson Cooper-Driver client_id, message_id,
473*479e2648SJackson Cooper-Driver error);
474*479e2648SJackson Cooper-Driver
475*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_send_message(link_id, (const uint8_t *)&packet,
476*479e2648SJackson Cooper-Driver SFCP_PACKET_SIZE_ERROR_REPLY);
477*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
478*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
479*479e2648SJackson Cooper-Driver }
480*479e2648SJackson Cooper-Driver
481*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
482*479e2648SJackson Cooper-Driver }
483*479e2648SJackson Cooper-Driver
sfcp_not_available_error(bool is_msg)484*479e2648SJackson Cooper-Driver static inline enum sfcp_error_t sfcp_not_available_error(bool is_msg)
485*479e2648SJackson Cooper-Driver {
486*479e2648SJackson Cooper-Driver return is_msg ? SFCP_ERROR_NO_MSG_AVAILABLE :
487*479e2648SJackson Cooper-Driver SFCP_ERROR_NO_REPLY_AVAILABLE;
488*479e2648SJackson Cooper-Driver }
489*479e2648SJackson Cooper-Driver
490*479e2648SJackson Cooper-Driver static enum sfcp_error_t
receive_msg_reply_from_node(uint8_t * buf,size_t buf_size,sfcp_node_id_t remote_id,sfcp_link_id_t * link_id,bool is_msg,size_t * received_size)491*479e2648SJackson Cooper-Driver receive_msg_reply_from_node(uint8_t *buf, size_t buf_size,
492*479e2648SJackson Cooper-Driver sfcp_node_id_t remote_id, sfcp_link_id_t *link_id,
493*479e2648SJackson Cooper-Driver bool is_msg, size_t *received_size)
494*479e2648SJackson Cooper-Driver {
495*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
496*479e2648SJackson Cooper-Driver bool is_available;
497*479e2648SJackson Cooper-Driver
498*479e2648SJackson Cooper-Driver *link_id = sfcp_hal_get_route(remote_id);
499*479e2648SJackson Cooper-Driver if (*link_id == 0) {
500*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
501*479e2648SJackson Cooper-Driver }
502*479e2648SJackson Cooper-Driver
503*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_is_message_available(*link_id, &is_available);
504*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
505*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
506*479e2648SJackson Cooper-Driver }
507*479e2648SJackson Cooper-Driver
508*479e2648SJackson Cooper-Driver if (!is_available) {
509*479e2648SJackson Cooper-Driver return sfcp_not_available_error(is_msg);
510*479e2648SJackson Cooper-Driver }
511*479e2648SJackson Cooper-Driver
512*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_get_receive_message_size(*link_id, received_size);
513*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
514*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
515*479e2648SJackson Cooper-Driver }
516*479e2648SJackson Cooper-Driver
517*479e2648SJackson Cooper-Driver if (*received_size > buf_size) {
518*479e2648SJackson Cooper-Driver return SFCP_ERROR_BUFFER_TOO_SMALL;
519*479e2648SJackson Cooper-Driver }
520*479e2648SJackson Cooper-Driver
521*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_receive_message(*link_id, buf, *received_size, 0,
522*479e2648SJackson Cooper-Driver *received_size);
523*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
524*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
525*479e2648SJackson Cooper-Driver }
526*479e2648SJackson Cooper-Driver
527*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
528*479e2648SJackson Cooper-Driver }
529*479e2648SJackson Cooper-Driver
530*479e2648SJackson Cooper-Driver static enum sfcp_error_t
receive_msg_reply(uint8_t * buf,size_t buf_size,bool any_remote_id,sfcp_node_id_t remote_id,sfcp_node_id_t * received_remote_id,sfcp_link_id_t * link_id,sfcp_link_id_t * my_node_id,bool is_msg,size_t * received_size)531*479e2648SJackson Cooper-Driver receive_msg_reply(uint8_t *buf, size_t buf_size, bool any_remote_id,
532*479e2648SJackson Cooper-Driver sfcp_node_id_t remote_id, sfcp_node_id_t *received_remote_id,
533*479e2648SJackson Cooper-Driver sfcp_link_id_t *link_id, sfcp_link_id_t *my_node_id,
534*479e2648SJackson Cooper-Driver bool is_msg, size_t *received_size)
535*479e2648SJackson Cooper-Driver {
536*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
537*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
538*479e2648SJackson Cooper-Driver sfcp_node_id_t start_node, end_node;
539*479e2648SJackson Cooper-Driver
540*479e2648SJackson Cooper-Driver /* We do not know if the remote will use the ID extension so ensure the
541*479e2648SJackson Cooper-Driver * buffer is large enough with it enabled
542*479e2648SJackson Cooper-Driver */
543*479e2648SJackson Cooper-Driver if (buf_size < SFCP_PACKET_SIZE_WITHOUT_PAYLOAD(true, true)) {
544*479e2648SJackson Cooper-Driver return SFCP_ERROR_BUFFER_TOO_SMALL;
545*479e2648SJackson Cooper-Driver }
546*479e2648SJackson Cooper-Driver
547*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_get_my_node_id(my_node_id);
548*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
549*479e2648SJackson Cooper-Driver return sfcp_hal_error_to_sfcp_error(hal_error);
550*479e2648SJackson Cooper-Driver }
551*479e2648SJackson Cooper-Driver
552*479e2648SJackson Cooper-Driver if (!any_remote_id && (remote_id == *my_node_id)) {
553*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
554*479e2648SJackson Cooper-Driver }
555*479e2648SJackson Cooper-Driver
556*479e2648SJackson Cooper-Driver if (any_remote_id) {
557*479e2648SJackson Cooper-Driver start_node = 0;
558*479e2648SJackson Cooper-Driver end_node = SFCP_NUMBER_NODES - 1;
559*479e2648SJackson Cooper-Driver } else {
560*479e2648SJackson Cooper-Driver start_node = remote_id;
561*479e2648SJackson Cooper-Driver end_node = remote_id;
562*479e2648SJackson Cooper-Driver }
563*479e2648SJackson Cooper-Driver
564*479e2648SJackson Cooper-Driver for (sfcp_node_id_t node = start_node; node <= end_node; node++) {
565*479e2648SJackson Cooper-Driver if (node == *my_node_id) {
566*479e2648SJackson Cooper-Driver continue;
567*479e2648SJackson Cooper-Driver }
568*479e2648SJackson Cooper-Driver
569*479e2648SJackson Cooper-Driver sfcp_err = receive_msg_reply_from_node(
570*479e2648SJackson Cooper-Driver buf, buf_size, node, link_id, is_msg, received_size);
571*479e2648SJackson Cooper-Driver if (sfcp_err == SFCP_ERROR_SUCCESS) {
572*479e2648SJackson Cooper-Driver *received_remote_id = node;
573*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
574*479e2648SJackson Cooper-Driver } else if (sfcp_err != sfcp_not_available_error(is_msg)) {
575*479e2648SJackson Cooper-Driver return sfcp_err;
576*479e2648SJackson Cooper-Driver }
577*479e2648SJackson Cooper-Driver }
578*479e2648SJackson Cooper-Driver
579*479e2648SJackson Cooper-Driver return sfcp_not_available_error(is_msg);
580*479e2648SJackson Cooper-Driver }
581*479e2648SJackson Cooper-Driver
sfcp_receive_msg(uint8_t * buf,size_t buf_size,bool any_sender,sfcp_node_id_t sender,uint16_t application_id,uint16_t * client_id,uint8_t ** payload,size_t * payload_len,struct sfcp_msg_metadata_t * metadata)582*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_receive_msg(uint8_t *buf, size_t buf_size,
583*479e2648SJackson Cooper-Driver bool any_sender, sfcp_node_id_t sender,
584*479e2648SJackson Cooper-Driver uint16_t application_id, uint16_t *client_id,
585*479e2648SJackson Cooper-Driver uint8_t **payload, size_t *payload_len,
586*479e2648SJackson Cooper-Driver struct sfcp_msg_metadata_t *metadata)
587*479e2648SJackson Cooper-Driver {
588*479e2648SJackson Cooper-Driver struct sfcp_packet_t *packet;
589*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
590*479e2648SJackson Cooper-Driver enum sfcp_protocol_error_t protocol_error;
591*479e2648SJackson Cooper-Driver enum sfcp_packet_type_t packet_type;
592*479e2648SJackson Cooper-Driver sfcp_link_id_t link_id;
593*479e2648SJackson Cooper-Driver sfcp_node_id_t my_node_id;
594*479e2648SJackson Cooper-Driver bool needs_reply;
595*479e2648SJackson Cooper-Driver bool uses_id_extension;
596*479e2648SJackson Cooper-Driver size_t received_size;
597*479e2648SJackson Cooper-Driver bool packet_uses_crypto;
598*479e2648SJackson Cooper-Driver uint16_t packet_application_id;
599*479e2648SJackson Cooper-Driver uint8_t message_id;
600*479e2648SJackson Cooper-Driver sfcp_node_id_t packet_sender;
601*479e2648SJackson Cooper-Driver sfcp_node_id_t packet_receiver;
602*479e2648SJackson Cooper-Driver sfcp_node_id_t forwarding_destination;
603*479e2648SJackson Cooper-Driver sfcp_node_id_t received_sender_id;
604*479e2648SJackson Cooper-Driver bool is_handshake_req;
605*479e2648SJackson Cooper-Driver
606*479e2648SJackson Cooper-Driver if ((buf == NULL) || (client_id == NULL) || (payload == NULL) ||
607*479e2648SJackson Cooper-Driver (payload_len == NULL) || (metadata == NULL)) {
608*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
609*479e2648SJackson Cooper-Driver }
610*479e2648SJackson Cooper-Driver
611*479e2648SJackson Cooper-Driver if (any_sender && (sender != 0)) {
612*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_SENDER_ID;
613*479e2648SJackson Cooper-Driver }
614*479e2648SJackson Cooper-Driver
615*479e2648SJackson Cooper-Driver sfcp_err = receive_msg_reply(buf, buf_size, any_sender, sender,
616*479e2648SJackson Cooper-Driver &received_sender_id, &link_id, &my_node_id,
617*479e2648SJackson Cooper-Driver true, &received_size);
618*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
619*479e2648SJackson Cooper-Driver return sfcp_err;
620*479e2648SJackson Cooper-Driver }
621*479e2648SJackson Cooper-Driver
622*479e2648SJackson Cooper-Driver packet = (struct sfcp_packet_t *)buf;
623*479e2648SJackson Cooper-Driver
624*479e2648SJackson Cooper-Driver sfcp_err = sfcp_helpers_parse_packet(
625*479e2648SJackson Cooper-Driver packet, received_size, &packet_sender, &packet_receiver,
626*479e2648SJackson Cooper-Driver &message_id, &packet_uses_crypto, &uses_id_extension,
627*479e2648SJackson Cooper-Driver &packet_application_id, client_id, payload, payload_len,
628*479e2648SJackson Cooper-Driver &needs_reply, &packet_type);
629*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
630*479e2648SJackson Cooper-Driver /* Do not know enough about this packet to reply */
631*479e2648SJackson Cooper-Driver return sfcp_err;
632*479e2648SJackson Cooper-Driver }
633*479e2648SJackson Cooper-Driver
634*479e2648SJackson Cooper-Driver if (sfcp_helpers_packet_requires_forwarding_get_destination(
635*479e2648SJackson Cooper-Driver packet_sender, packet_receiver, packet_type, my_node_id,
636*479e2648SJackson Cooper-Driver &forwarding_destination)) {
637*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_FORWARDING_UNSUPPORTED;
638*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_NO_MSG_AVAILABLE;
639*479e2648SJackson Cooper-Driver goto error_reply;
640*479e2648SJackson Cooper-Driver }
641*479e2648SJackson Cooper-Driver
642*479e2648SJackson Cooper-Driver sfcp_err = sfcp_encryption_handshake_responder(
643*479e2648SJackson Cooper-Driver packet, received_size,
644*479e2648SJackson Cooper-Driver packet_type == SFCP_PACKET_TYPE_REPLY ? packet_receiver :
645*479e2648SJackson Cooper-Driver packet_sender,
646*479e2648SJackson Cooper-Driver message_id, packet_uses_crypto, *payload, *payload_len,
647*479e2648SJackson Cooper-Driver &is_handshake_req);
648*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
649*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_HANDSHAKE_FAILED;
650*479e2648SJackson Cooper-Driver goto error_reply;
651*479e2648SJackson Cooper-Driver }
652*479e2648SJackson Cooper-Driver
653*479e2648SJackson Cooper-Driver if (is_handshake_req) {
654*479e2648SJackson Cooper-Driver /* Handshake message has been successfully handled, nothing else to do */
655*479e2648SJackson Cooper-Driver return SFCP_ERROR_NO_MSG_AVAILABLE;
656*479e2648SJackson Cooper-Driver }
657*479e2648SJackson Cooper-Driver
658*479e2648SJackson Cooper-Driver if ((packet_type != SFCP_PACKET_TYPE_MSG_NEEDS_REPLY) &&
659*479e2648SJackson Cooper-Driver (packet_type != SFCP_PACKET_TYPE_MSG_NO_REPLY)) {
660*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_INVALID_CONTEXT;
661*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_NO_MSG_AVAILABLE;
662*479e2648SJackson Cooper-Driver goto error_reply;
663*479e2648SJackson Cooper-Driver }
664*479e2648SJackson Cooper-Driver
665*479e2648SJackson Cooper-Driver if ((packet_sender != received_sender_id) ||
666*479e2648SJackson Cooper-Driver (packet_receiver != my_node_id)) {
667*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_UNSUPPORTED;
668*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_INVALID_NODE;
669*479e2648SJackson Cooper-Driver goto error_reply;
670*479e2648SJackson Cooper-Driver }
671*479e2648SJackson Cooper-Driver
672*479e2648SJackson Cooper-Driver if (!uses_id_extension && (application_id != 0)) {
673*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_UNSUPPORTED;
674*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_INVALID_APPLICATION_ID;
675*479e2648SJackson Cooper-Driver goto error_reply;
676*479e2648SJackson Cooper-Driver }
677*479e2648SJackson Cooper-Driver
678*479e2648SJackson Cooper-Driver if (uses_id_extension && (packet_application_id != application_id)) {
679*479e2648SJackson Cooper-Driver /* This message is not for us so we have to drop and get the remote to
680*479e2648SJackson Cooper-Driver * send it again later
681*479e2648SJackson Cooper-Driver */
682*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_TRY_AGAIN_LATER;
683*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_NO_MSG_AVAILABLE;
684*479e2648SJackson Cooper-Driver goto error_reply;
685*479e2648SJackson Cooper-Driver }
686*479e2648SJackson Cooper-Driver
687*479e2648SJackson Cooper-Driver if (packet_uses_crypto) {
688*479e2648SJackson Cooper-Driver sfcp_err = sfcp_decrypt_msg(packet, received_size,
689*479e2648SJackson Cooper-Driver received_sender_id);
690*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
691*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_DECRYPTION_FAILED;
692*479e2648SJackson Cooper-Driver goto error_reply;
693*479e2648SJackson Cooper-Driver }
694*479e2648SJackson Cooper-Driver }
695*479e2648SJackson Cooper-Driver
696*479e2648SJackson Cooper-Driver populate_msg_metadata(
697*479e2648SJackson Cooper-Driver metadata, received_sender_id, packet_uses_crypto, *client_id,
698*479e2648SJackson Cooper-Driver application_id, message_id,
699*479e2648SJackson Cooper-Driver packet_uses_crypto ?
700*479e2648SJackson Cooper-Driver packet->cryptography_used.cryptography_metadata.config
701*479e2648SJackson Cooper-Driver .trusted_subnet_id :
702*479e2648SJackson Cooper-Driver 0);
703*479e2648SJackson Cooper-Driver
704*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
705*479e2648SJackson Cooper-Driver
706*479e2648SJackson Cooper-Driver error_reply:
707*479e2648SJackson Cooper-Driver if (needs_reply) {
708*479e2648SJackson Cooper-Driver enum sfcp_error_t send_reply_error = send_protocol_error(
709*479e2648SJackson Cooper-Driver packet_sender, packet_receiver, link_id, *client_id,
710*479e2648SJackson Cooper-Driver message_id, protocol_error);
711*479e2648SJackson Cooper-Driver if (send_reply_error != SFCP_ERROR_SUCCESS) {
712*479e2648SJackson Cooper-Driver return send_reply_error;
713*479e2648SJackson Cooper-Driver }
714*479e2648SJackson Cooper-Driver }
715*479e2648SJackson Cooper-Driver
716*479e2648SJackson Cooper-Driver return sfcp_err;
717*479e2648SJackson Cooper-Driver }
718*479e2648SJackson Cooper-Driver
sfcp_receive_reply(uint8_t * buf,size_t buf_size,struct sfcp_reply_metadata_t metadata,uint8_t ** payload,size_t * payload_len)719*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_receive_reply(uint8_t *buf, size_t buf_size,
720*479e2648SJackson Cooper-Driver struct sfcp_reply_metadata_t metadata,
721*479e2648SJackson Cooper-Driver uint8_t **payload, size_t *payload_len)
722*479e2648SJackson Cooper-Driver {
723*479e2648SJackson Cooper-Driver struct sfcp_packet_t *packet;
724*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
725*479e2648SJackson Cooper-Driver enum sfcp_protocol_error_t protocol_error;
726*479e2648SJackson Cooper-Driver enum sfcp_packet_type_t packet_type;
727*479e2648SJackson Cooper-Driver sfcp_link_id_t link_id;
728*479e2648SJackson Cooper-Driver sfcp_link_id_t my_node_id;
729*479e2648SJackson Cooper-Driver bool needs_reply;
730*479e2648SJackson Cooper-Driver bool uses_id_extension;
731*479e2648SJackson Cooper-Driver size_t received_size = 0;
732*479e2648SJackson Cooper-Driver bool packet_uses_crypto;
733*479e2648SJackson Cooper-Driver uint16_t packet_application_id;
734*479e2648SJackson Cooper-Driver uint16_t packet_client_id;
735*479e2648SJackson Cooper-Driver sfcp_node_id_t packet_sender;
736*479e2648SJackson Cooper-Driver sfcp_node_id_t packet_receiver;
737*479e2648SJackson Cooper-Driver sfcp_node_id_t forwarding_destination;
738*479e2648SJackson Cooper-Driver sfcp_node_id_t received_receiver_id;
739*479e2648SJackson Cooper-Driver uint8_t message_id;
740*479e2648SJackson Cooper-Driver
741*479e2648SJackson Cooper-Driver if ((buf == NULL) || (payload == NULL) || (payload_len == NULL)) {
742*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
743*479e2648SJackson Cooper-Driver }
744*479e2648SJackson Cooper-Driver
745*479e2648SJackson Cooper-Driver sfcp_err = receive_msg_reply(buf, buf_size, false, metadata.receiver,
746*479e2648SJackson Cooper-Driver &received_receiver_id, &link_id,
747*479e2648SJackson Cooper-Driver &my_node_id, false, &received_size);
748*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
749*479e2648SJackson Cooper-Driver return sfcp_err;
750*479e2648SJackson Cooper-Driver }
751*479e2648SJackson Cooper-Driver
752*479e2648SJackson Cooper-Driver packet = (struct sfcp_packet_t *)buf;
753*479e2648SJackson Cooper-Driver
754*479e2648SJackson Cooper-Driver sfcp_err = sfcp_helpers_parse_packet(
755*479e2648SJackson Cooper-Driver packet, received_size, &packet_sender, &packet_receiver,
756*479e2648SJackson Cooper-Driver &message_id, &packet_uses_crypto, &uses_id_extension,
757*479e2648SJackson Cooper-Driver &packet_application_id, &packet_client_id, payload, payload_len,
758*479e2648SJackson Cooper-Driver &needs_reply, &packet_type);
759*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
760*479e2648SJackson Cooper-Driver /* Do not know enough about this packet to reply */
761*479e2648SJackson Cooper-Driver return sfcp_err;
762*479e2648SJackson Cooper-Driver }
763*479e2648SJackson Cooper-Driver
764*479e2648SJackson Cooper-Driver if (sfcp_helpers_packet_requires_forwarding_get_destination(
765*479e2648SJackson Cooper-Driver packet_sender, packet_receiver, packet_type, my_node_id,
766*479e2648SJackson Cooper-Driver &forwarding_destination)) {
767*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_FORWARDING_UNSUPPORTED;
768*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_NO_REPLY_AVAILABLE;
769*479e2648SJackson Cooper-Driver goto error_reply;
770*479e2648SJackson Cooper-Driver }
771*479e2648SJackson Cooper-Driver
772*479e2648SJackson Cooper-Driver if ((packet_type != SFCP_PACKET_TYPE_PROTOCOL_ERROR_REPLY) &&
773*479e2648SJackson Cooper-Driver (packet_type != SFCP_PACKET_TYPE_REPLY)) {
774*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_TRY_AGAIN_LATER;
775*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_NO_REPLY_AVAILABLE;
776*479e2648SJackson Cooper-Driver goto error_reply;
777*479e2648SJackson Cooper-Driver }
778*479e2648SJackson Cooper-Driver
779*479e2648SJackson Cooper-Driver /* Message is definitely not something we need to reply
780*479e2648SJackson Cooper-Driver * to, so we can just return an error to the caller
781*479e2648SJackson Cooper-Driver */
782*479e2648SJackson Cooper-Driver
783*479e2648SJackson Cooper-Driver if ((packet_sender != my_node_id) ||
784*479e2648SJackson Cooper-Driver (packet_receiver != received_receiver_id)) {
785*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
786*479e2648SJackson Cooper-Driver }
787*479e2648SJackson Cooper-Driver
788*479e2648SJackson Cooper-Driver if (!uses_id_extension && (metadata.client_id != 0)) {
789*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_CLIENT_ID;
790*479e2648SJackson Cooper-Driver }
791*479e2648SJackson Cooper-Driver
792*479e2648SJackson Cooper-Driver if (packet_type == SFCP_PACKET_TYPE_PROTOCOL_ERROR_REPLY) {
793*479e2648SJackson Cooper-Driver if (packet_client_id == metadata.client_id) {
794*479e2648SJackson Cooper-Driver /* Error message for us */
795*479e2648SJackson Cooper-Driver return sfcp_protocol_error_to_sfcp_error(
796*479e2648SJackson Cooper-Driver packet->error_reply.protocol_error);
797*479e2648SJackson Cooper-Driver } else {
798*479e2648SJackson Cooper-Driver /* Error message for a different client ID, drop */
799*479e2648SJackson Cooper-Driver return SFCP_ERROR_NO_REPLY_AVAILABLE;
800*479e2648SJackson Cooper-Driver }
801*479e2648SJackson Cooper-Driver }
802*479e2648SJackson Cooper-Driver
803*479e2648SJackson Cooper-Driver if (uses_id_extension && (packet_client_id != metadata.client_id)) {
804*479e2648SJackson Cooper-Driver /* This reply is not for us so we have to drop it */
805*479e2648SJackson Cooper-Driver return SFCP_ERROR_NO_REPLY_AVAILABLE;
806*479e2648SJackson Cooper-Driver }
807*479e2648SJackson Cooper-Driver
808*479e2648SJackson Cooper-Driver if (uses_id_extension &&
809*479e2648SJackson Cooper-Driver (packet_application_id != metadata.application_id)) {
810*479e2648SJackson Cooper-Driver /* Message has the client ID so it is for us, but the sender has not correctly
811*479e2648SJackson Cooper-Driver * set the application ID, drop
812*479e2648SJackson Cooper-Driver */
813*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_APPLICATION_ID;
814*479e2648SJackson Cooper-Driver }
815*479e2648SJackson Cooper-Driver
816*479e2648SJackson Cooper-Driver if (packet_uses_crypto != metadata.uses_cryptography) {
817*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_CRYPTO_MODE;
818*479e2648SJackson Cooper-Driver }
819*479e2648SJackson Cooper-Driver
820*479e2648SJackson Cooper-Driver if (message_id != metadata.message_id) {
821*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_SEQUENCE_NUMBER;
822*479e2648SJackson Cooper-Driver }
823*479e2648SJackson Cooper-Driver
824*479e2648SJackson Cooper-Driver if (packet_uses_crypto) {
825*479e2648SJackson Cooper-Driver sfcp_err = sfcp_decrypt_reply(packet, received_size,
826*479e2648SJackson Cooper-Driver received_receiver_id);
827*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
828*479e2648SJackson Cooper-Driver return sfcp_err;
829*479e2648SJackson Cooper-Driver }
830*479e2648SJackson Cooper-Driver }
831*479e2648SJackson Cooper-Driver
832*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
833*479e2648SJackson Cooper-Driver
834*479e2648SJackson Cooper-Driver error_reply:
835*479e2648SJackson Cooper-Driver if (needs_reply) {
836*479e2648SJackson Cooper-Driver enum sfcp_error_t send_reply_error = send_protocol_error(
837*479e2648SJackson Cooper-Driver packet_sender, packet_receiver, link_id,
838*479e2648SJackson Cooper-Driver packet_client_id, message_id, protocol_error);
839*479e2648SJackson Cooper-Driver if (send_reply_error != SFCP_ERROR_SUCCESS) {
840*479e2648SJackson Cooper-Driver return send_reply_error;
841*479e2648SJackson Cooper-Driver }
842*479e2648SJackson Cooper-Driver }
843*479e2648SJackson Cooper-Driver
844*479e2648SJackson Cooper-Driver return sfcp_err;
845*479e2648SJackson Cooper-Driver }
846*479e2648SJackson Cooper-Driver
sfcp_get_msg_handler(uint16_t application_id,sfcp_handler_t * handler)847*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_get_msg_handler(uint16_t application_id,
848*479e2648SJackson Cooper-Driver sfcp_handler_t *handler)
849*479e2648SJackson Cooper-Driver {
850*479e2648SJackson Cooper-Driver if (handler == NULL) {
851*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
852*479e2648SJackson Cooper-Driver }
853*479e2648SJackson Cooper-Driver
854*479e2648SJackson Cooper-Driver for (uint8_t i = 0; i < SFCP_MAX_NUMBER_MESSAGE_HANDLERS; i++) {
855*479e2648SJackson Cooper-Driver if (sfcp_msg_handlers[i].in_use &&
856*479e2648SJackson Cooper-Driver (sfcp_msg_handlers[i].application_id == application_id)) {
857*479e2648SJackson Cooper-Driver *handler = sfcp_msg_handlers[i].handler;
858*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
859*479e2648SJackson Cooper-Driver }
860*479e2648SJackson Cooper-Driver }
861*479e2648SJackson Cooper-Driver
862*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_APPLICATION_ID;
863*479e2648SJackson Cooper-Driver }
864*479e2648SJackson Cooper-Driver
sfcp_register_msg_handler(uint16_t application_id,sfcp_handler_t handler)865*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_register_msg_handler(uint16_t application_id,
866*479e2648SJackson Cooper-Driver sfcp_handler_t handler)
867*479e2648SJackson Cooper-Driver {
868*479e2648SJackson Cooper-Driver if (handler == NULL) {
869*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
870*479e2648SJackson Cooper-Driver }
871*479e2648SJackson Cooper-Driver
872*479e2648SJackson Cooper-Driver for (uint8_t i = 0; i < SFCP_MAX_NUMBER_MESSAGE_HANDLERS; i++) {
873*479e2648SJackson Cooper-Driver if (!sfcp_msg_handlers[i].in_use) {
874*479e2648SJackson Cooper-Driver sfcp_msg_handlers[i].handler = handler;
875*479e2648SJackson Cooper-Driver sfcp_msg_handlers[i].application_id = application_id;
876*479e2648SJackson Cooper-Driver sfcp_msg_handlers[i].in_use = true;
877*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
878*479e2648SJackson Cooper-Driver }
879*479e2648SJackson Cooper-Driver }
880*479e2648SJackson Cooper-Driver
881*479e2648SJackson Cooper-Driver return SFCP_ERROR_HANDLER_TABLE_FULL;
882*479e2648SJackson Cooper-Driver }
883*479e2648SJackson Cooper-Driver
sfcp_pop_msg_from_buffer(sfcp_buffer_handle_t buffer_handle,sfcp_node_id_t * sender,uint16_t * client_id,bool * needs_reply,uint8_t * payload,size_t payload_len,size_t * payload_size,struct sfcp_msg_metadata_t * metadata)884*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_pop_msg_from_buffer(sfcp_buffer_handle_t buffer_handle,
885*479e2648SJackson Cooper-Driver sfcp_node_id_t *sender,
886*479e2648SJackson Cooper-Driver uint16_t *client_id,
887*479e2648SJackson Cooper-Driver bool *needs_reply, uint8_t *payload,
888*479e2648SJackson Cooper-Driver size_t payload_len,
889*479e2648SJackson Cooper-Driver size_t *payload_size,
890*479e2648SJackson Cooper-Driver struct sfcp_msg_metadata_t *metadata)
891*479e2648SJackson Cooper-Driver {
892*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
893*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
894*479e2648SJackson Cooper-Driver enum sfcp_protocol_error_t protocol_error;
895*479e2648SJackson Cooper-Driver struct sfcp_packet_t *packet;
896*479e2648SJackson Cooper-Driver enum sfcp_packet_type_t packet_type;
897*479e2648SJackson Cooper-Driver sfcp_node_id_t my_node_id;
898*479e2648SJackson Cooper-Driver size_t packet_size;
899*479e2648SJackson Cooper-Driver bool packet_uses_id_extension, packet_uses_crypto;
900*479e2648SJackson Cooper-Driver sfcp_node_id_t packet_receiver;
901*479e2648SJackson Cooper-Driver uint8_t *packet_payload;
902*479e2648SJackson Cooper-Driver size_t packet_payload_size;
903*479e2648SJackson Cooper-Driver uint8_t message_id;
904*479e2648SJackson Cooper-Driver uint16_t packet_application_id;
905*479e2648SJackson Cooper-Driver
906*479e2648SJackson Cooper-Driver if ((sender == NULL) || (client_id == NULL) || (needs_reply == NULL) ||
907*479e2648SJackson Cooper-Driver (payload_size == NULL) || (metadata == NULL)) {
908*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
909*479e2648SJackson Cooper-Driver }
910*479e2648SJackson Cooper-Driver
911*479e2648SJackson Cooper-Driver if ((payload_len != 0) && (payload == NULL)) {
912*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
913*479e2648SJackson Cooper-Driver }
914*479e2648SJackson Cooper-Driver
915*479e2648SJackson Cooper-Driver sfcp_err = sfcp_get_handler_buffer(buffer_handle, (uint8_t **)&packet,
916*479e2648SJackson Cooper-Driver &packet_size);
917*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
918*479e2648SJackson Cooper-Driver return sfcp_err;
919*479e2648SJackson Cooper-Driver }
920*479e2648SJackson Cooper-Driver
921*479e2648SJackson Cooper-Driver sfcp_err = sfcp_helpers_parse_packet(
922*479e2648SJackson Cooper-Driver packet, packet_size, sender, &packet_receiver, &message_id,
923*479e2648SJackson Cooper-Driver &packet_uses_crypto, &packet_uses_id_extension,
924*479e2648SJackson Cooper-Driver &packet_application_id, client_id, &packet_payload,
925*479e2648SJackson Cooper-Driver &packet_payload_size, needs_reply, &packet_type);
926*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
927*479e2648SJackson Cooper-Driver /* Do not know enough about this packet to reply */
928*479e2648SJackson Cooper-Driver return sfcp_err;
929*479e2648SJackson Cooper-Driver }
930*479e2648SJackson Cooper-Driver
931*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_get_my_node_id(&my_node_id);
932*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
933*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_INTERNAL_ERROR;
934*479e2648SJackson Cooper-Driver sfcp_err = sfcp_hal_error_to_sfcp_error(hal_error);
935*479e2648SJackson Cooper-Driver goto error_reply;
936*479e2648SJackson Cooper-Driver }
937*479e2648SJackson Cooper-Driver
938*479e2648SJackson Cooper-Driver if ((packet_type != SFCP_PACKET_TYPE_MSG_NEEDS_REPLY) &&
939*479e2648SJackson Cooper-Driver (packet_type != SFCP_PACKET_TYPE_MSG_NO_REPLY)) {
940*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_INVALID_CONTEXT;
941*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_NO_MSG_AVAILABLE;
942*479e2648SJackson Cooper-Driver goto error_reply;
943*479e2648SJackson Cooper-Driver }
944*479e2648SJackson Cooper-Driver
945*479e2648SJackson Cooper-Driver if (packet_receiver != my_node_id) {
946*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_UNSUPPORTED;
947*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_INVALID_NODE;
948*479e2648SJackson Cooper-Driver goto error_reply;
949*479e2648SJackson Cooper-Driver }
950*479e2648SJackson Cooper-Driver
951*479e2648SJackson Cooper-Driver if (packet_payload_size > payload_len) {
952*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_MSG_TOO_LARGE_TO_RECIEVE;
953*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_PAYLOAD_TOO_LARGE;
954*479e2648SJackson Cooper-Driver goto error_reply;
955*479e2648SJackson Cooper-Driver }
956*479e2648SJackson Cooper-Driver
957*479e2648SJackson Cooper-Driver if (packet_uses_crypto) {
958*479e2648SJackson Cooper-Driver sfcp_err = sfcp_decrypt_msg(packet, packet_size, *sender);
959*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
960*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_DECRYPTION_FAILED;
961*479e2648SJackson Cooper-Driver goto error_reply;
962*479e2648SJackson Cooper-Driver }
963*479e2648SJackson Cooper-Driver }
964*479e2648SJackson Cooper-Driver
965*479e2648SJackson Cooper-Driver memcpy(payload, packet_payload, packet_payload_size);
966*479e2648SJackson Cooper-Driver *payload_size = packet_payload_size;
967*479e2648SJackson Cooper-Driver
968*479e2648SJackson Cooper-Driver populate_msg_metadata(
969*479e2648SJackson Cooper-Driver metadata, *sender, packet_uses_crypto, *client_id,
970*479e2648SJackson Cooper-Driver packet_application_id, message_id,
971*479e2648SJackson Cooper-Driver packet_uses_crypto ?
972*479e2648SJackson Cooper-Driver packet->cryptography_used.cryptography_metadata.config
973*479e2648SJackson Cooper-Driver .trusted_subnet_id :
974*479e2648SJackson Cooper-Driver 0);
975*479e2648SJackson Cooper-Driver
976*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_SUCCESS;
977*479e2648SJackson Cooper-Driver goto pop_message;
978*479e2648SJackson Cooper-Driver
979*479e2648SJackson Cooper-Driver error_reply:
980*479e2648SJackson Cooper-Driver if (*needs_reply) {
981*479e2648SJackson Cooper-Driver enum sfcp_error_t send_reply_error;
982*479e2648SJackson Cooper-Driver sfcp_link_id_t link_id;
983*479e2648SJackson Cooper-Driver
984*479e2648SJackson Cooper-Driver link_id = sfcp_hal_get_route(*sender);
985*479e2648SJackson Cooper-Driver if (link_id == 0) {
986*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
987*479e2648SJackson Cooper-Driver }
988*479e2648SJackson Cooper-Driver
989*479e2648SJackson Cooper-Driver send_reply_error = send_protocol_error(*sender, packet_receiver,
990*479e2648SJackson Cooper-Driver link_id, *client_id,
991*479e2648SJackson Cooper-Driver message_id,
992*479e2648SJackson Cooper-Driver protocol_error);
993*479e2648SJackson Cooper-Driver if (send_reply_error != SFCP_ERROR_SUCCESS) {
994*479e2648SJackson Cooper-Driver return send_reply_error;
995*479e2648SJackson Cooper-Driver }
996*479e2648SJackson Cooper-Driver }
997*479e2648SJackson Cooper-Driver
998*479e2648SJackson Cooper-Driver pop_message: {
999*479e2648SJackson Cooper-Driver enum sfcp_error_t pop_buffer_sfcp_error =
1000*479e2648SJackson Cooper-Driver sfcp_pop_handler_buffer(buffer_handle);
1001*479e2648SJackson Cooper-Driver if (pop_buffer_sfcp_error != SFCP_ERROR_SUCCESS) {
1002*479e2648SJackson Cooper-Driver return pop_buffer_sfcp_error;
1003*479e2648SJackson Cooper-Driver }
1004*479e2648SJackson Cooper-Driver }
1005*479e2648SJackson Cooper-Driver
1006*479e2648SJackson Cooper-Driver return sfcp_err;
1007*479e2648SJackson Cooper-Driver }
1008*479e2648SJackson Cooper-Driver
sfcp_get_reply_handler(uint16_t client_id,sfcp_handler_t * handler)1009*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_get_reply_handler(uint16_t client_id,
1010*479e2648SJackson Cooper-Driver sfcp_handler_t *handler)
1011*479e2648SJackson Cooper-Driver {
1012*479e2648SJackson Cooper-Driver for (uint8_t i = 0; i < SFCP_MAX_NUMBER_REPLY_HANDLERS; i++) {
1013*479e2648SJackson Cooper-Driver if (sfcp_reply_handlers[i].in_use &&
1014*479e2648SJackson Cooper-Driver (sfcp_reply_handlers[i].client_id == client_id)) {
1015*479e2648SJackson Cooper-Driver *handler = sfcp_reply_handlers[i].handler;
1016*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
1017*479e2648SJackson Cooper-Driver }
1018*479e2648SJackson Cooper-Driver }
1019*479e2648SJackson Cooper-Driver
1020*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_CLIENT_ID;
1021*479e2648SJackson Cooper-Driver }
1022*479e2648SJackson Cooper-Driver
sfcp_register_reply_handler(uint16_t client_id,sfcp_handler_t handler)1023*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_register_reply_handler(uint16_t client_id,
1024*479e2648SJackson Cooper-Driver sfcp_handler_t handler)
1025*479e2648SJackson Cooper-Driver {
1026*479e2648SJackson Cooper-Driver for (uint8_t i = 0; i < SFCP_MAX_NUMBER_REPLY_HANDLERS; i++) {
1027*479e2648SJackson Cooper-Driver if (!sfcp_reply_handlers[i].in_use) {
1028*479e2648SJackson Cooper-Driver sfcp_reply_handlers[i].handler = handler;
1029*479e2648SJackson Cooper-Driver sfcp_reply_handlers[i].client_id = client_id;
1030*479e2648SJackson Cooper-Driver sfcp_reply_handlers[i].in_use = true;
1031*479e2648SJackson Cooper-Driver return SFCP_ERROR_SUCCESS;
1032*479e2648SJackson Cooper-Driver }
1033*479e2648SJackson Cooper-Driver }
1034*479e2648SJackson Cooper-Driver
1035*479e2648SJackson Cooper-Driver return SFCP_ERROR_HANDLER_TABLE_FULL;
1036*479e2648SJackson Cooper-Driver }
1037*479e2648SJackson Cooper-Driver
1038*479e2648SJackson Cooper-Driver enum sfcp_error_t
sfcp_pop_reply_from_buffer(sfcp_buffer_handle_t buffer_handle,uint8_t * payload,size_t payload_len,size_t * payload_size,struct sfcp_reply_metadata_t * metadata)1039*479e2648SJackson Cooper-Driver sfcp_pop_reply_from_buffer(sfcp_buffer_handle_t buffer_handle, uint8_t *payload,
1040*479e2648SJackson Cooper-Driver size_t payload_len, size_t *payload_size,
1041*479e2648SJackson Cooper-Driver struct sfcp_reply_metadata_t *metadata)
1042*479e2648SJackson Cooper-Driver {
1043*479e2648SJackson Cooper-Driver enum sfcp_error_t sfcp_err;
1044*479e2648SJackson Cooper-Driver enum sfcp_hal_error_t hal_error;
1045*479e2648SJackson Cooper-Driver enum sfcp_protocol_error_t protocol_error;
1046*479e2648SJackson Cooper-Driver struct sfcp_packet_t *packet;
1047*479e2648SJackson Cooper-Driver enum sfcp_packet_type_t packet_type;
1048*479e2648SJackson Cooper-Driver sfcp_node_id_t my_node_id;
1049*479e2648SJackson Cooper-Driver size_t packet_size;
1050*479e2648SJackson Cooper-Driver bool packet_uses_id_extension, packet_uses_crypto;
1051*479e2648SJackson Cooper-Driver bool needs_reply;
1052*479e2648SJackson Cooper-Driver sfcp_node_id_t packet_sender, packet_receiver;
1053*479e2648SJackson Cooper-Driver uint8_t *packet_payload;
1054*479e2648SJackson Cooper-Driver size_t packet_payload_size;
1055*479e2648SJackson Cooper-Driver uint8_t message_id;
1056*479e2648SJackson Cooper-Driver uint16_t packet_application_id, packet_client_id;
1057*479e2648SJackson Cooper-Driver
1058*479e2648SJackson Cooper-Driver if ((payload_size == NULL) || (metadata == NULL)) {
1059*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
1060*479e2648SJackson Cooper-Driver }
1061*479e2648SJackson Cooper-Driver
1062*479e2648SJackson Cooper-Driver if ((payload_len != 0) && (payload == NULL)) {
1063*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_POINTER;
1064*479e2648SJackson Cooper-Driver }
1065*479e2648SJackson Cooper-Driver
1066*479e2648SJackson Cooper-Driver sfcp_err = sfcp_get_handler_buffer(buffer_handle, (uint8_t **)&packet,
1067*479e2648SJackson Cooper-Driver &packet_size);
1068*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
1069*479e2648SJackson Cooper-Driver return sfcp_err;
1070*479e2648SJackson Cooper-Driver }
1071*479e2648SJackson Cooper-Driver
1072*479e2648SJackson Cooper-Driver sfcp_err = sfcp_helpers_parse_packet(
1073*479e2648SJackson Cooper-Driver packet, packet_size, &packet_sender, &packet_receiver,
1074*479e2648SJackson Cooper-Driver &message_id, &packet_uses_crypto, &packet_uses_id_extension,
1075*479e2648SJackson Cooper-Driver &packet_application_id, &packet_client_id, &packet_payload,
1076*479e2648SJackson Cooper-Driver &packet_payload_size, &needs_reply, &packet_type);
1077*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
1078*479e2648SJackson Cooper-Driver /* Do not know enough about this packet to reply */
1079*479e2648SJackson Cooper-Driver return sfcp_err;
1080*479e2648SJackson Cooper-Driver }
1081*479e2648SJackson Cooper-Driver
1082*479e2648SJackson Cooper-Driver hal_error = sfcp_hal_get_my_node_id(&my_node_id);
1083*479e2648SJackson Cooper-Driver if (hal_error != SFCP_HAL_ERROR_SUCCESS) {
1084*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_INTERNAL_ERROR;
1085*479e2648SJackson Cooper-Driver sfcp_err = sfcp_hal_error_to_sfcp_error(hal_error);
1086*479e2648SJackson Cooper-Driver goto error_reply;
1087*479e2648SJackson Cooper-Driver }
1088*479e2648SJackson Cooper-Driver
1089*479e2648SJackson Cooper-Driver if ((packet_type != SFCP_PACKET_TYPE_PROTOCOL_ERROR_REPLY) &&
1090*479e2648SJackson Cooper-Driver (packet_type != SFCP_PACKET_TYPE_REPLY)) {
1091*479e2648SJackson Cooper-Driver protocol_error = SFCP_PROTOCOL_ERROR_TRY_AGAIN_LATER;
1092*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_NO_REPLY_AVAILABLE;
1093*479e2648SJackson Cooper-Driver goto error_reply;
1094*479e2648SJackson Cooper-Driver }
1095*479e2648SJackson Cooper-Driver
1096*479e2648SJackson Cooper-Driver /* Message is definitely not something we need to reply
1097*479e2648SJackson Cooper-Driver * to, so we can just return an error to the caller
1098*479e2648SJackson Cooper-Driver */
1099*479e2648SJackson Cooper-Driver
1100*479e2648SJackson Cooper-Driver if (packet_sender != my_node_id) {
1101*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
1102*479e2648SJackson Cooper-Driver }
1103*479e2648SJackson Cooper-Driver
1104*479e2648SJackson Cooper-Driver if (packet_type == SFCP_PACKET_TYPE_PROTOCOL_ERROR_REPLY) {
1105*479e2648SJackson Cooper-Driver return sfcp_protocol_error_to_sfcp_error(
1106*479e2648SJackson Cooper-Driver packet->error_reply.protocol_error);
1107*479e2648SJackson Cooper-Driver }
1108*479e2648SJackson Cooper-Driver
1109*479e2648SJackson Cooper-Driver if (packet_payload_size > payload_len) {
1110*479e2648SJackson Cooper-Driver return SFCP_ERROR_PAYLOAD_TOO_LARGE;
1111*479e2648SJackson Cooper-Driver }
1112*479e2648SJackson Cooper-Driver
1113*479e2648SJackson Cooper-Driver if (packet_uses_crypto) {
1114*479e2648SJackson Cooper-Driver sfcp_err = sfcp_decrypt_reply(packet, packet_size,
1115*479e2648SJackson Cooper-Driver packet_receiver);
1116*479e2648SJackson Cooper-Driver if (sfcp_err != SFCP_ERROR_SUCCESS) {
1117*479e2648SJackson Cooper-Driver return sfcp_err;
1118*479e2648SJackson Cooper-Driver }
1119*479e2648SJackson Cooper-Driver }
1120*479e2648SJackson Cooper-Driver
1121*479e2648SJackson Cooper-Driver memcpy(payload, packet_payload, packet_payload_size);
1122*479e2648SJackson Cooper-Driver *payload_size = packet_payload_size;
1123*479e2648SJackson Cooper-Driver
1124*479e2648SJackson Cooper-Driver populate_reply_metadata(
1125*479e2648SJackson Cooper-Driver metadata, packet_receiver, packet_uses_crypto, packet_client_id,
1126*479e2648SJackson Cooper-Driver packet_application_id, message_id,
1127*479e2648SJackson Cooper-Driver packet_uses_crypto ?
1128*479e2648SJackson Cooper-Driver packet->cryptography_used.cryptography_metadata.config
1129*479e2648SJackson Cooper-Driver .trusted_subnet_id :
1130*479e2648SJackson Cooper-Driver 0);
1131*479e2648SJackson Cooper-Driver
1132*479e2648SJackson Cooper-Driver sfcp_err = SFCP_ERROR_SUCCESS;
1133*479e2648SJackson Cooper-Driver goto pop_message;
1134*479e2648SJackson Cooper-Driver
1135*479e2648SJackson Cooper-Driver error_reply:
1136*479e2648SJackson Cooper-Driver if (needs_reply) {
1137*479e2648SJackson Cooper-Driver enum sfcp_error_t send_reply_error;
1138*479e2648SJackson Cooper-Driver sfcp_link_id_t link_id;
1139*479e2648SJackson Cooper-Driver
1140*479e2648SJackson Cooper-Driver link_id = sfcp_hal_get_route(packet_sender);
1141*479e2648SJackson Cooper-Driver if (link_id == 0) {
1142*479e2648SJackson Cooper-Driver return SFCP_ERROR_INVALID_NODE;
1143*479e2648SJackson Cooper-Driver }
1144*479e2648SJackson Cooper-Driver
1145*479e2648SJackson Cooper-Driver send_reply_error = send_protocol_error(
1146*479e2648SJackson Cooper-Driver packet_sender, packet_receiver, link_id,
1147*479e2648SJackson Cooper-Driver packet_client_id, message_id, protocol_error);
1148*479e2648SJackson Cooper-Driver if (send_reply_error != SFCP_ERROR_SUCCESS) {
1149*479e2648SJackson Cooper-Driver return send_reply_error;
1150*479e2648SJackson Cooper-Driver }
1151*479e2648SJackson Cooper-Driver }
1152*479e2648SJackson Cooper-Driver
1153*479e2648SJackson Cooper-Driver pop_message: {
1154*479e2648SJackson Cooper-Driver enum sfcp_error_t pop_buffer_sfcp_error =
1155*479e2648SJackson Cooper-Driver sfcp_pop_handler_buffer(buffer_handle);
1156*479e2648SJackson Cooper-Driver if (pop_buffer_sfcp_error != SFCP_ERROR_SUCCESS) {
1157*479e2648SJackson Cooper-Driver return pop_buffer_sfcp_error;
1158*479e2648SJackson Cooper-Driver }
1159*479e2648SJackson Cooper-Driver }
1160*479e2648SJackson Cooper-Driver
1161*479e2648SJackson Cooper-Driver return sfcp_err;
1162*479e2648SJackson Cooper-Driver }
1163