xref: /rk3399_ARM-atf/drivers/arm/sfcp/sfcp_core/sfcp.c (revision 2801427972c4b0d4c0165edb509f21186103f21f)
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