#ifndef cp_msg_msg_h #define cp_msg_msg_h /* Cesar project {{{ * * Copyright (C) 2008 Spidcom * * <<>> * * }}} */ /** * \file cp/msg/msg.h * \brief MME creation and decoding. * \ingroup cp_msg * * The msg module handles: * * - messages decoding, * - messages encoding, * - messages dispatch, * - encrypted payload encapsulation, * - relaying encapsulation. */ #include "cp/cp.h" #include "cp/mme.h" #include "cp/defs.h" #include "cp/msg/inc/msg_cc.h" #include "cp/msg/inc/msg_cm.h" #include "cp/msg/inc/msg_drv.h" #include "cp/msg/inc/msg_vs.h" enum cp_msg_avln_status_t { CP_MSG_AVLN_STATUS_UNASSOC_CCO_0, CP_MSG_AVLN_STATUS_UNASSOC_CCO_1, CP_MSG_AVLN_STATUS_UNASSOC_CCO_2, CP_MSG_AVLN_STATUS_UNASSOC_CCO_3, CP_MSG_AVLN_STATUS_ASSOC_NOT_PCO, CP_MSG_AVLN_STATUS_ASSOC_PCO, CP_MSG_AVLN_STATUS_CCO = 0x8, CP_MSG_AVLN_STATUS_NB }; BEGIN_DECLS /** * Initialise the MSG module. * \param ctx control plane context */ void cp_msg_init (cp_t *ctx); /** * Uninitialise the MSG module. * \param ctx control plane context */ void cp_msg_uninit (cp_t *ctx); /** * Examine message type and post an event to the FSM. * \param ctx control plane context * \param mme received MME * * This function looks up the message type and translates it to a FSM event, * while checking the encryption is compliant with the message type. * * It also extracts and checks payload from encrypted messages. */ void cp_msg_dispatch (cp_t *ctx, cp_mme_rx_t *mme); /** * Initialise a MME handle for a new message to be transmitted. * \param ctx control plane context * \param peer peer information * \param mmtype the MME MMTYPE. * \return the newly created message * * This function: * * - gets a buffer for MME transmission, * - encapsulates the MME in a CC_RELAY.REQ if necessary, * - writes the MME header. */ cp_mme_tx_t * cp_msg_mme_init_not_frag (cp_t *ctx, cp_mme_peer_t *peer, mmtype_t mmtype); /** * Initialise a MME handle for a new encrypted message to be transmitted. * \param ctx control plane context * \param peer peer information * \param mmtype the MME MMType. * \param pid protocol identifier * \param peks payload encryption key select * \param prun protocol run information * \return the newly created message * * This does the same as cp_msg_mme_init_not_frag(), but also encapsulate the * MME in a CM_ENCRYPTED_PAYLOAD.IND. */ cp_mme_tx_t * cp_msg_mme_init_encrypted (cp_t *ctx, cp_mme_peer_t *peer, mmtype_t mmtype, cp_mme_peks_t peks, const cp_secu_protocol_run_t *prun); /** Write the header of a fragmented MME. * \param ctx the ctx module. * \param msg the MME context. * \param bs the bitstream context. * \param the MMTYPE of the MME useful for the encrypted MME. */ void cp_msg_mme_write_frag_header (cp_t *ctx, cp_mme_tx_t *msg, bitstream_t *bs, mmtype_t mmtype); /** * Initialise a MME handle for a new message fragment to be transmitted. * \param ctx control plane context * \param peer peer information * \param mmtype the MME MMTYPE. * \param mme_payload_length total payload size in byte. * \return the newly created message */ cp_mme_tx_t * cp_msg_mme_init (cp_t *ctx, cp_mme_peer_t *peer, mmtype_t mmtype, uint mme_payload_length); /** * Initialise a MME handle for a new message fragment to be transmitted. * \param ctx control plane context * \param peer peer information * \param mmtype the MME MMTYPE. * \param fmi_nbFrag The number of fragments. * \param fmi_nb the number of the fragment. * \return the newly created message * * This function: * * - gets a buffer for MME transmission, * - encapsulates the MME in a CC_RELAY.REQ if necessary, * - writes the MME header. */ cp_mme_tx_t * cp_msg_mme_init_frag (cp_t *ctx, cp_mme_peer_t *peer, mmtype_t mmtype, uint fmi_nbFrag); /** * Finalise and send a MME. * \param ctx control plane context * \param mme MME handle * * If the MME is encapsulated, write any pending footer, then send the * message. */ void cp_msg_mme_send (cp_t *ctx, cp_mme_tx_t *mme); /** Read the MME header once the bitstream has already been initialised. * \param mme the MME handler. * \param fmi the FMI. */ bool cp_msg_mme_read_header_initialised (cp_mme_rx_t *mme, uint *fmi); /** * Read the header of a received MME and return the MME context. * \param ctx the module context. * \param mme the MME received. * \param length the MME length. * \param tei the source TEI (0xFF if coming from the HLE). * \param fmi the FMI data. * \return cp_mme_rx_t object associated. * * If the MME is not correct the MME will be dropped. */ cp_mme_rx_t * cp_msg_mme_read_header (cp_t *ctx, u8 *mme, uint length, cp_tei_t tei, uint *fmi); /** * Read an encrypted header and decrypt the payload. * \param ctx the module context. * \param mme the mme context. * \return true if decoded correctly, false otherwise. */ bool cp_msg_mme_read_header_enc (cp_t *ctx, cp_mme_rx_t *mme); /** * Change the current buffer of the reception message. * \param msg the message RX to change the buffer. * * This shall be used only on the RX MMEs which are received as fragmented * ones. */ void cp_msg_mme_rx_change_buffer (cp_mme_rx_t *msg); /** Function to call when the buffer is full. * \param bs the bitstream context. * \param data the structure registered. */ void cp_msg_mme_tx_change_buffer (bitstream_t *bs, cp_mme_tx_t *mme); /** * Callback called by bitstream when no more bytes are available. * \param ctx the bitstream context. * \param user_data the jmp_buf used by the setjmp. * * This callback should be set by each MME read function, each time a * bitstream read is called and the MME has no more bits to read the bitstream * should call this function. * The result is a longjmp called with a error value to detect the errors in * MMEs. * See #425 for more details. */ void cp_msg_mme_read_error_process (bitstream_t *ctx, void *user_data); /** * Initialise the read error case using bitstream * \param ctx the module context. * \param mme the MME rx context. * \return true if no error, false otherwise. * * See #425 for more detail. */ #define cp_msg_mme_read_error(ctx, mme) \ ({ \ dbg_assert (ctx); \ dbg_assert (mme); \ bitstream_init_buffer_cb (&mme->bitstream, \ cp_msg_mme_read_error_process, mme); \ setjmp (mme->jump_env) == 0; \ }) /** Verify if the whole MME has been read. * \param ctx the module context. * \param mme the mme context. * \return true if the whole MME has been read. */ static inline bool cp_msg_mme_read_end_check (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert (ctx); dbg_assert (mme); if ((mme->length > ETH_PACKET_MIN_SIZE) && ((bitstream_available_bits (&mme->bitstream) / 8) != 0)) return false; return true; } END_DECLS #endif /* cp_msg_msg_h */