/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipl2tp_v2_message.c,v $ $Revision: 1.2 $ * $Source: /home/interpeak/CVSRoot/ipl2tp/src/ipl2tp_v2_message.c,v $ * $Author: joel $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #include "ipl2tp_h.h" #include "ipl2tp_avp.h" #include "ipl2tp_data.h" #include "ipl2tp_message.h" #include "ipl2tp_state.h" #include "ipl2tp_trpt.h" #include "ipl2tp_v2.h" #include "ipl2tp_v2_state.h" #include "ipl2tp_v2_message.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_zlb(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_cdn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_occn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_ocrq(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_ocrp(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_iccn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_icrq(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_icrp(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_hello(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_stopccn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_scccn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_sccrp(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); IP_STATIC Ipl2tp_status ipl2tp_v2_message_sccrq(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp); /* **************************************************************************** * 8 DATA **************************************************************************** */ /* Message callback table */ Ipl2tp_message_func ipl2tp_v2_messages[IPL2TP_MSG_MAX] = { ipl2tp_v2_message_zlb, /* 0 ZLB */ ipl2tp_v2_message_sccrq, /* 1 SCCRQ */ ipl2tp_v2_message_sccrp, /* 2 SCCRP */ ipl2tp_v2_message_scccn, /* 3 SCCCN */ ipl2tp_v2_message_stopccn, /* 4 STOPCCN */ IP_NULL, /* 5 RESERVED */ ipl2tp_v2_message_hello, /* 6 HELLO */ ipl2tp_v2_message_ocrq, /* 7 OCRQ */ ipl2tp_v2_message_ocrp, /* 8 OCRP */ ipl2tp_v2_message_occn, /* 9 OCCN */ ipl2tp_v2_message_icrq, /* 10 ICRQ */ ipl2tp_v2_message_icrp, /* 11 ICRP */ ipl2tp_v2_message_iccn, /* 12 ICCN */ IP_NULL, /* 13 RESERVED */ ipl2tp_v2_message_cdn, /* 14 CDN */ IP_NULL, /* 15 WEN */ IP_NULL, /* 16 SLI */ IP_NULL, /* 17 MDMST */ IP_NULL, /* 18 SRRQ */ IP_NULL, /* 19 SRRP */ IP_NULL /* 20 ACK */ }; /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipl2tp_v2_message_sccrq *=========================================================================== * Description: Create and send an SCCRQ message. * Parameters: tunnel - Pointer to tunnel descriptor. * session - The session (NULL) * avp - AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_sccrq(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel, IP_NULL); IPL2TP_UNUSED(avp); IPL2TP_UNUSED(session); if (c != IP_NULL) { /* Compulsory part */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_SCCRQ); ipl2tp_v2_message_sccrq_avps(tunnel, c); ipl2tp_avp_set_host_name(c, ipl2tp.host_name); ipl2tp_avp_set_vendor_name(c, IPL2TP_VENDOR_NAME); if (ipl2tp.open_exclusive == IPL2TP_MIB_NO) { Ipl2tp_vector vec; Ip_u8 data[8]; vec.array = data; ipl2tp_util_vector_random(&vec, 8); ipl2tp_avp_set_tie_breaker(c, &vec); ipl2tp_util_vector_dup(&tunnel->common.tie_breaker, &vec); } ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_sccrp *=========================================================================== * Description: Create and send an SCCRP message. * Parameters: tunnel - The tunnel * session - The session (NULL) * avp - The AVP we're replying to. * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_sccrp(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel, IP_NULL); Ipl2tp_vector resp; IPL2TP_UNUSED(session); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_SCCRP); ipl2tp_avp_set_protocol_version(c); ipl2tp_avp_set_host_name(c, ipl2tp.host_name); ipl2tp_avp_set_framing_capabilities(c, tunnel->attr.framing_capabilities); ipl2tp_avp_set_assigned_tunnel_id(c, tunnel->local.key.ident); if (tunnel->attr.bearer_capabilities != 0) { ipl2tp_avp_set_bearer_capabilities(c, tunnel->attr.bearer_capabilities); } if (tunnel->attr.receive_window_size != IPL2TP_RECEIVE_WINDOW_SIZE) { ipl2tp_avp_set_receive_window_size(c, tunnel->attr.receive_window_size); } /* Generate challenge if applicable */ if (tunnel->attr.authentication == IPL2TP_MIB_AUTH_CHALLENGE) { Ip_u8 cvalue[IPL2TP_MAX_CHALLENGE_LENGTH]; Ipl2tp_vector vec; vec.array = cvalue; vec.size = IPL2TP_MAX_CHALLENGE_LENGTH; ipl2tp_avp_challenge_init(&vec, tunnel, IPL2TP_MSG_SCCRP); ipl2tp_avp_set_challenge(c, &vec); } /* Reply to challenge if necessary */ switch (ipl2tp_avp_challenge_response_init(&resp, tunnel, avp)) { case IPL2TP_STATUS_OK: ipl2tp_avp_set_challenge_response(c, &resp); break; case IPL2TP_STATUS_IGNORE: break; default: ipl2tp_message_delete(c); return IPL2TP_STATUS_ERROR; } /* Free it if it's used */ IPL2TP_SAFE_FREE(resp.array); ipl2tp_avp_set_firmware_revision(c, IPL2TP_VERSION_NUM); ipl2tp_avp_set_vendor_name(c, IPL2TP_VENDOR_NAME); ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_scccn *=========================================================================== * Description: Create and send an SCCCN message. * Parameters: tunnel - The tunnel * session - The session (NULL) * avp - The AVP * Returns: IPL2TP_STATUS_OK if it went OK * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_scccn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel, IP_NULL); Ipl2tp_vector resp; IPL2TP_UNUSED(session); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_SCCCN); /* Reply to challenge if necessary */ switch (ipl2tp_avp_challenge_response_init(&resp, tunnel, avp)) { case IPL2TP_STATUS_OK: ipl2tp_avp_set_challenge_response(c, &resp); break; case IPL2TP_STATUS_IGNORE: break; default: ipl2tp_message_delete(c); return IPL2TP_STATUS_ERROR; } IPL2TP_SAFE_FREE(resp.array); ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_stopccn *=========================================================================== * Description: Create and send a StopCCN message. * Parameters: tunnel - The tunnel. * session - The session (NULL) * avp - AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_stopccn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { IPL2TP_UNUSED(session); IPL2TP_UNUSED(avp); if (tunnel->state != IPL2TP_TSTATE_TEARDOWN) { Ipl2tp_message *c = ipl2tp_message_new(tunnel, IP_NULL); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_StopCCN); ipl2tp_avp_set_assigned_tunnel_id(c, tunnel->local.key.ident); ipl2tp_avp_set_result_code(c, tunnel->last_result.result_code, tunnel->last_result.error_code, tunnel->last_result.error_message); /* Purge output queue to be sure the StopCCN is sent */ ipl2tp_state_tunnel_flush(tunnel); ipl2tp_trpt_control_output(c); } } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_hello *=========================================================================== * Description: Create and send a HELLO message. * Parameters: tunnel - Pointer to tunnel descriptor. * session - Session (NULL) * avp - The AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_hello(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel, IP_NULL); IPL2TP_UNUSED(avp); IPL2TP_UNUSED(session); if (c != IP_NULL) { ipl2tp_avp_set_message_type(c, IPL2TP_MSG_HELLO); ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_icrq *=========================================================================== * Description: Create and send an ICRQ message. * Parameters: tunnel - The tunnel * session - Pointer to session descriptor. * avp - AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_icrq(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel,session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_ICRQ); ipl2tp_avp_set_assigned_session_id(c, session->local.key.ident); ipl2tp_avp_set_call_serial_number(c, session->common.call_serial_number); if (session->attr.bearer_type != 0) { ipl2tp_avp_set_bearer_type(c, session->attr.bearer_type); } if (session->attr.calling_number != IP_NULL) { ipl2tp_avp_set_calling_number(c, session->attr.calling_number); } if (session->attr.called_number != IP_NULL) { ipl2tp_avp_set_called_number(c, session->attr.called_number); } if (session->attr.phys_chan_id != 0) { ipl2tp_avp_set_physical_channel_id(c, session->attr.phys_chan_id); } if (session->attr.sub_address != IP_NULL) { ipl2tp_avp_set_sub_address(c, session->attr.sub_address); } ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_icrp *=========================================================================== * Description: Create and send an ICRP message. * Parameters: tunnel - The tunnel * session - Pointer to session descriptor. * avp - AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_icrp(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel,session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_ICRP); ipl2tp_avp_set_assigned_session_id(c, session->local.key.ident); ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_iccn *=========================================================================== * Description: Create and send an ICCN message. * Parameters: tunnel - The tunnel * session - Pointer to session descriptor. * avp - AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_iccn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel,session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_ICCN); ipl2tp_avp_set_tx_connect_speed(c, session->attr.tx_connect_speed); ipl2tp_avp_set_framing_type(c, session->attr.framing_type); if (session->attr.rx_connect_speed != 0) { ipl2tp_avp_set_rx_connect_speed(c, session->attr.rx_connect_speed); } if (session->attr.private_group_id != IP_NULL) { ipl2tp_avp_set_private_group_id(c, session->attr.private_group_id); } if (session->tunnel->attr.sequencing == IPL2TP_MIB_ALWAYS) { ipl2tp_avp_set_sequencing_required(c); } if (session->attr.first_received_confreq.size != 0) { ipl2tp_avp_set_initial_received_lcp_confreq(c, &session->attr.first_received_confreq); } if (session->attr.last_received_confreq.size != 0) { ipl2tp_avp_set_last_received_lcp_confreq(c, &session->attr.last_received_confreq); } else if (session->attr.first_received_confreq.size != 0) { /* If single CONFREQ, last == first */ ipl2tp_avp_set_last_received_lcp_confreq(c, &session->attr.first_received_confreq); } if (session->attr.last_sent_confreq.size != 0) { ipl2tp_avp_set_last_sent_lcp_confreq(c, &session->attr.last_sent_confreq); } if (session->attr.auth_method != 0) { ipl2tp_avp_set_proxy_authen_type(c, session->attr.auth_method); } if (session->attr.proxy_authen_name != IP_NULL) { ipl2tp_avp_set_proxy_authen_name(c, session->attr.proxy_authen_name); } if (session->attr.proxy_authen_challenge.size != 0) { ipl2tp_avp_set_proxy_authen_challenge(c, &session->attr.proxy_authen_challenge); } if (session->attr.proxy_authen_id != 0) { ipl2tp_avp_set_proxy_authen_id(c, session->attr.proxy_authen_id); } if (session->attr.proxy_authen_response.size != 0) { ipl2tp_avp_set_proxy_authen_response(c, &session->attr.proxy_authen_response); } ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_ocrq *=========================================================================== * Description: Create and send an OCRQ message. * Parameters: tunnel - The tunnel * session - Pointer to session descriptor. * avp - AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_ocrq(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel,session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_OCRQ); ipl2tp_avp_set_assigned_session_id(c, session->local.key.ident); ipl2tp_avp_set_call_serial_number(c, session->common.call_serial_number); ipl2tp_avp_set_minimum_bps(c, session->attr.minimum_bps); ipl2tp_avp_set_maximum_bps(c, session->attr.maximum_bps); ipl2tp_avp_set_framing_type(c, session->attr.framing_type); if (session->attr.bearer_type != 0) { ipl2tp_avp_set_bearer_type(c, session->attr.bearer_type); } if (session->attr.called_number != IP_NULL) { ipl2tp_avp_set_called_number(c, session->attr.called_number); } if (session->attr.sub_address != IP_NULL) { ipl2tp_avp_set_sub_address(c, session->attr.sub_address); } ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_ocrp *=========================================================================== * Description: Create and send an OCRP message. * Parameters: tunnel - The tunnel * session - Pointer to session descriptor. * avp - AVP (NULL) * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_ocrp(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel,session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_OCRP); ipl2tp_avp_set_assigned_session_id(c, session->local.key.ident); if (session->attr.phys_chan_id != 0) { ipl2tp_avp_set_physical_channel_id(c, session->attr.phys_chan_id); } ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_occn *=========================================================================== * Description: Create and send an OCCN message. * Parameters: * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_occn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel,session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_OCCN); ipl2tp_avp_set_tx_connect_speed(c, session->attr.tx_connect_speed); ipl2tp_avp_set_framing_type(c, session->attr.framing_type); if (session->attr.rx_connect_speed != 0) { ipl2tp_avp_set_rx_connect_speed(c, session->attr.rx_connect_speed); } if (session->tunnel->attr.sequencing == IPL2TP_MIB_ALWAYS) { ipl2tp_avp_set_sequencing_required(c); } ipl2tp_trpt_control_output(c); } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_cdn *=========================================================================== * Description: Create and send a CDN message. * Parameters: * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_cdn(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { IPL2TP_UNUSED(avp); if (session->state != IPL2TP_SSTATE_WAIT_TUNNEL) { Ipl2tp_message *c = ipl2tp_message_new(tunnel,session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { /* Prepare message */ ipl2tp_avp_set_message_type(c, IPL2TP_MSG_CDN); ipl2tp_avp_set_assigned_session_id(c, session->local.key.ident); ipl2tp_avp_set_result_code(c, tunnel->last_result.result_code, tunnel->last_result.error_code, tunnel->last_result.error_message); ipl2tp_trpt_control_output(c); } } return IPL2TP_STATUS_OK; } /* *=========================================================================== * ipl2tp_v2_message_zlb *=========================================================================== * Description: Create and send a ZLB message. * Parameters: * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_v2_message_zlb(Ipl2tp_tunnel *tunnel, Ipl2tp_session *session, Ipl2tp_avp *avp) { Ipl2tp_message *c = ipl2tp_message_new(tunnel, IP_NULL); IPL2TP_UNUSED(session); IPL2TP_UNUSED(avp); if (c != IP_NULL) { ipl2tp_message_is_zlb(c); ipl2tp_trpt_control_output(c); tunnel->statistics.control_zlb_sent++; } return IPL2TP_STATUS_OK; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipl2tp_v2_message_sccrq *=========================================================================== * Description: Create and send an SCCRQ message. * Parameters: tunnel - Pointer to tunnel descriptor. * session - The session (NULL) * avp - AVP (NULL) * Returns: * */ IP_GLOBAL Ipl2tp_status ipl2tp_v2_message_sccrq_avps(Ipl2tp_tunnel *tunnel, Ipl2tp_message *c) { /* Compulsory part */ ipl2tp_avp_set_protocol_version(c); ipl2tp_avp_set_framing_capabilities(c, tunnel->attr.framing_capabilities); ipl2tp_avp_set_assigned_tunnel_id(c, tunnel->local.key.ident); /* Optional part */ if (tunnel->attr.bearer_capabilities != 0) { ipl2tp_avp_set_bearer_capabilities(c, tunnel->attr.bearer_capabilities); } if (tunnel->attr.receive_window_size != IPL2TP_RECEIVE_WINDOW_SIZE) { ipl2tp_avp_set_receive_window_size(c, tunnel->attr.receive_window_size); } /* Generate challenge if applicable */ if (tunnel->attr.authentication == IPL2TP_MIB_AUTH_CHALLENGE) { Ip_u8 cvalue[IPL2TP_MAX_CHALLENGE_LENGTH]; Ipl2tp_vector vec; vec.array = cvalue; vec.size = IPL2TP_MAX_CHALLENGE_LENGTH; ipl2tp_avp_challenge_init(&vec, tunnel, IPL2TP_MSG_SCCRQ); ipl2tp_avp_set_challenge(c, &vec); } ipl2tp_avp_set_firmware_revision(c, IPL2TP_VERSION_NUM); return IPL2TP_STATUS_OK; } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */