1417 lines
43 KiB
C
1417 lines
43 KiB
C
/* ipdiameter_tx.c - Diameter packet transmission routines */
|
|
|
|
/*
|
|
* Copyright (c) 2007 Wind River Systems, Inc.
|
|
*
|
|
* The right to copy, distribute or otherwise make use of this software
|
|
* may be licensed only pursuant to the terms of an applicable Wind River
|
|
* license agreement. No license to Wind River intellectual property rights
|
|
* is granted herein. All rights not licensed by Wind River are reserved
|
|
* by Wind River.
|
|
*/
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01l,20mar09,tlu Add function to format and send out RAA pkts
|
|
01k,10mar09,tlu Fix Linux build warning
|
|
01j,06feb09,tlu Modify ASA and STR pkt to use application's appl id in
|
|
the pkt's header
|
|
01i,10oct07,tlu Port to Linux
|
|
01h,20sep07,tlu Take a peer's semaphore before transmiting over the peer's
|
|
TLS connection
|
|
01g,19sep07,tlu Modify file name comment for apigen
|
|
01f,13aug07,tlu Add TLS support
|
|
01e,10jul07,tlu Reset tried server flag if found a reachable server
|
|
01d,06jul07,tlu Add redundant server handling
|
|
01c,04jul07,tlu Add application ID AVPs to CER/CEA packets
|
|
01b,19jun07,tlu Add AVP flag and vendor_id to ipdiameter_avp_add_** functions
|
|
01a,12apr07,tlu Created.
|
|
*/
|
|
|
|
/*
|
|
DESCRIPTION
|
|
This library provides routines to transmit Diameter packets.
|
|
|
|
To use this feature, include the following component: INCLUDE_IPDIAMETERC
|
|
|
|
INCLUDE FILES: ipdiameter.h
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_time.h>
|
|
#include <ipcom_clib.h>
|
|
|
|
#include "ipdiameter.h"
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_EXTERN Ipdiameter_data ipdiameter;
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* This is a compile flag, turning on it will build debug message into image */
|
|
#undef DIAMETER_DEBUG
|
|
|
|
/* The following are for Open Diameter tests */
|
|
#undef OPEN_DIAMETER_TEST
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_pkt_send
|
|
*===========================================================================
|
|
* Description: send the diameter message out
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_pkt_send(Ip_fd fd, SSL *ssl, Ipdiameter_header *package)
|
|
{
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Ip_u32 code, length;
|
|
#ifdef IPSSL
|
|
int len;
|
|
#endif /* IPSSL */
|
|
|
|
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("Calling ipdiameter_pkt_send, fd %d, ssl %ld\n", fd, ssl);
|
|
#endif
|
|
|
|
if (fd == IP_INVALID_SOCKET)
|
|
return IPDIAMETER_ERR_NO_SERVER;
|
|
|
|
if (package == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_pkt_send(): NULL package");
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
code = ipdiameter_get_hdr_code((Ip_u32 *)package);
|
|
length = ipdiameter_get_hdr_length((Ip_u32 *)package);
|
|
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("ipdiameter_pkt_send -> tx DIAMETER packet [code=%lu, flags=%x, length=%lu, appl_id=%lu, hbh_id=%lu, e2e_id=%lu]\n",
|
|
code, package->flags, length, ip_ntohl(package->appl_id),
|
|
ip_ntohl(package->hbh_id), ip_ntohl(package->e2e_id));
|
|
ipdiameter_print_pkt(package);
|
|
#endif
|
|
|
|
|
|
#ifdef IPSSL
|
|
if (ssl != IP_NULL)
|
|
{
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("ipdiameter_pkt_send: write to TLS, ssl %d\n", ssl);
|
|
#endif
|
|
len = ipdiameter_tls_write(ssl, (char *)package, length);
|
|
if (len == 0)
|
|
{
|
|
IPCOM_LOG2(WARNING, "ipdiameter_pkt_send(): tls_write(%d, %d) failed",
|
|
fd, ssl);
|
|
|
|
/* peer closed the connection */
|
|
retval = IPCOM_ERR_FAILED;
|
|
}
|
|
}
|
|
else
|
|
#endif /* IPSSL */
|
|
{
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("ipdiameter_pkt_send: write to socket %d\n", fd);
|
|
#endif
|
|
/* Use ipcom_sendto() to transmit the DIAMETER TCP packet. */
|
|
if (ipcom_send(fd, package, length, 0) == IP_SOCKERR)
|
|
{
|
|
Ip_socklen_t optlen;
|
|
int error;
|
|
|
|
IPCOM_LOG2(WARNING, "ipdiameter_pkt_send(): ipcom_sendto(%d) failed : %s",
|
|
fd,
|
|
ipcom_strerror(ipcom_errno));
|
|
|
|
/* Clear socket errno. */
|
|
optlen = sizeof(error);
|
|
(void)ipcom_getsockopt(fd, IP_SOL_SOCKET, IP_SO_ERROR, &error, &optlen);
|
|
retval = IP_SOCKERR;
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_session_pkt_send
|
|
*===========================================================================
|
|
* Description: send the diameter message to the server associated with the session
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_session_pkt_send(Ipdiameter_session *session, Ipdiameter_header *package)
|
|
{
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Ip_fd fd = IP_INVALID_SOCKET;
|
|
Ipdiameter_peer_entry *peer;
|
|
Ip_u32 length;
|
|
Ip_u8 *data;
|
|
Ip_s8 index_v;
|
|
|
|
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("Calling ipdiameter_session_pkt_send\n");
|
|
ipdiameter_print_session(session);
|
|
#endif
|
|
|
|
if (session == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_session_pkt_send: invalid session specified\n");
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
/* Add Session-ID AVP if not already present */
|
|
retval = ipdiameter_get_avp(package, DIAMETER_AVP_CODE_Session_Id, &length, &data);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
/* Add Session-Id AVP */
|
|
length = (Ip_u32)ipcom_strlen(session->session_id);
|
|
(void)ipdiameter_avp_add_array(package, DIAMETER_AVP_CODE_Session_Id,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL,
|
|
(Ip_u8 *)session->session_id, length);
|
|
}
|
|
|
|
/* decide next hop to send the packet */
|
|
if (session->peer == IP_NULL)
|
|
{
|
|
peer = (Ipdiameter_peer_entry *)ipdiameter_session_select_route(session);
|
|
|
|
/* select a different server if cannot find next hop */
|
|
while (peer == IP_NULL)
|
|
{
|
|
if (ipdiameter_set_server(session) == IPCOM_SUCCESS)
|
|
{
|
|
peer = (Ipdiameter_peer_entry *)ipdiameter_session_select_route(session);
|
|
if (peer)
|
|
{
|
|
ipdiameter_session_update_reqs(session);
|
|
|
|
/* Found route, reset the tried server record */
|
|
ipdiameter_reset_tried_servers(session);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_session_pkt_send: cannot find a route\n");
|
|
return IPCOM_ERR_NO_ROUTE;
|
|
}
|
|
}
|
|
|
|
ipdiameter_session_set_peer(session, (struct Ipdiameter_peer_entry *)peer);
|
|
}
|
|
else
|
|
peer = (Ipdiameter_peer_entry *)session->peer;
|
|
|
|
|
|
/* start a timer for the request packet */
|
|
retval = ipdiameter_pkt_start_timer(package);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(WARNING, "ipdiameter_session_pkt_send: failed to start re-transmission timer\n");
|
|
|
|
if ((peer->state == DIAMETER_PEER_STATE_R_OPEN) ||
|
|
(peer->state == DIAMETER_PEER_STATE_I_OPEN))
|
|
goto transmit;
|
|
|
|
retval = ipdiameter_peer_add_tx_pending_pkt(peer,
|
|
(struct Ipdiameter_header *)package);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_session_pkt_send: fail to add package to peer's transmiting list\n");
|
|
return retval;
|
|
}
|
|
|
|
|
|
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_START);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_session_pkt_send: fail to run peer FSM\n");
|
|
|
|
return retval;
|
|
|
|
transmit:
|
|
/* Pick matching IPv4 or IPv6 socket. */
|
|
index_v = session->selected_server;
|
|
#ifdef IPCOM_USE_INET
|
|
if (((Ipdiameter_server *)session->serv_list[index_v])->server_addr.sa.sa_family == IP_AF_INET)
|
|
fd = ((Ipdiameter_peer_entry *)session->peer)->fd;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (((Ipdiameter_server *)session->serv_list[index_v])->server_addr.sa.sa_family == IP_AF_INET6)
|
|
fd = ((Ipdiameter_peer_entry *)session->peer)->fd6;
|
|
#endif
|
|
|
|
if (fd == IP_INVALID_SOCKET)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipdiameter_session_pkt_send: No valid socket descriptor to send to peer %s",
|
|
ipdiameter_addr_to_str(&((Ipdiameter_peer_entry *)session->peer)->peer_addr));
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("ipdiameter_session_pkt_send: socket descriptor %d, to send to peer %s\n",
|
|
fd, ipdiameter_addr_to_str(&((Ipdiameter_peer_entry *)session->peer)->peer_addr));
|
|
#endif
|
|
|
|
ipdiameter_pkt_set_starttime(package);
|
|
|
|
/* Send the packet out */
|
|
IPDIAMETER_PEER_LOCK(peer);
|
|
retval = ipdiameter_pkt_send(fd, peer->ssl, package);
|
|
IPDIAMETER_PEER_UNLOCK(peer);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_session_pkt_send: failed to send out the package\n");
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ipdiameter_peer_pkt_send - send a Diameter package out to a peer
|
|
*
|
|
* This routine transmits a Diameter package to a Diameter peer.
|
|
*
|
|
* Note that this function is exported to application API to be used
|
|
* only by ipdiameter_register_access_function(). Applications must NOT
|
|
* modify any fields in the peer structure.
|
|
*
|
|
* Parameters:
|
|
*
|
|
* \is
|
|
* \i <peer>
|
|
* Diameter peer.
|
|
* \i <package>
|
|
* A Diameter package.
|
|
* \ie
|
|
*
|
|
* RETURNS:
|
|
* \is
|
|
* \i IPCOM_SUCCESS
|
|
* \i IPCOM_ERR_INVALID_ARG if peer is NULL
|
|
* \i IPCOM_ERR_FAILED if it fails to send out the package
|
|
* \ie
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err ipdiameter_peer_pkt_send
|
|
(
|
|
Ipdiameter_peer_entry *peer,
|
|
Ipdiameter_header *package
|
|
)
|
|
{
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Ip_fd fd = IP_INVALID_SOCKET;
|
|
|
|
if (peer == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_peer_pkt_send: invalid peer specified\n");
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
/* Pick matching IPv4 or IPv6 socket. */
|
|
#ifdef IPCOM_USE_INET
|
|
if (peer->peer_addr.sa.sa_family == IP_AF_INET)
|
|
fd = peer->fd;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (peer->peer_addr.sa.sa_family == IP_AF_INET6)
|
|
fd = peer->fd6;
|
|
#endif
|
|
|
|
if (fd == IP_INVALID_SOCKET)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipdiameter_peer_pkt_send: No valid socket descriptor to send to peer %s",
|
|
ipdiameter_addr_to_str(&peer->peer_addr));
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("ipdiameter_peer_pkt_send: fd %d, to send to peer %s\n",
|
|
fd, ipdiameter_addr_to_str(&peer->peer_addr));
|
|
#endif
|
|
|
|
ipdiameter_pkt_set_starttime(package);
|
|
|
|
/* start a timer for the request packet */
|
|
retval = ipdiameter_pkt_start_timer(package);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(WARNING, "ipdiameter_peer_pkt_send: failed to start re-transmission timer\n");
|
|
|
|
/* Send the packet out */
|
|
IPDIAMETER_PEER_LOCK(peer);
|
|
retval = ipdiameter_pkt_send(fd, peer->ssl, package);
|
|
IPDIAMETER_PEER_UNLOCK(peer);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_peer_pkt_send: failed to send out the package\n");
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_ASA
|
|
*===========================================================================
|
|
* Description: Complete an abort session answer packet and send out
|
|
*
|
|
* 8.5.2. Abort-Session-Answer
|
|
*
|
|
* The Abort-Session-Answer (ASA), indicated by the Command-Code set to
|
|
* 274 and the message flags' 'R' bit clear, is sent in response to the
|
|
* ASR. The Result-Code AVP MUST be present, and indicates the
|
|
* disposition of the request.
|
|
*
|
|
* If the session identified by Session-Id in the ASR was successfully
|
|
* terminated, Result-Code is set to DIAMETER_SUCCESS. If the session
|
|
* is not currently active, Result-Code is set to
|
|
* DIAMETER_UNKNOWN_SESSION_ID. If the access device does not stop the
|
|
* session for any other reason, Result-Code is set to
|
|
* DIAMETER_UNABLE_TO_COMPLY.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <ASA> ::= < Diameter Header: 274, PXY >
|
|
* < Session-Id >
|
|
* { Result-Code }
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* [ User-Name ]
|
|
* [ Origin-State-Id ]
|
|
* [ Error-Message ]
|
|
* [ Error-Reporting-Host ]
|
|
* * [ Failed-AVP ]
|
|
* * [ Redirect-Host ]
|
|
* [ Redirect-Host-Usage ]
|
|
* [ Redirect-Max-Cache-Time ]
|
|
* * [ Proxy-Info ]
|
|
* * [ AVP ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_ASA(Ipdiameter_session *session, Ip_fd fd, SSL *ssl,
|
|
Ipdiameter_header *ASR_package, Ip_u32 result_code)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Ip_u8 *user_name = IP_NULL;
|
|
char session_id[IPDIAMETER_MAX_SESSION_ID_SIZE] = IPDIAMETER_NULL_STRING;
|
|
|
|
|
|
message = ipdiameter_answer_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Abort_Session_Answer);
|
|
message->appl_id = ASR_package->appl_id;
|
|
message->hbh_id = ASR_package->hbh_id;
|
|
message->e2e_id = ASR_package->e2e_id;
|
|
|
|
/* Get Session-Id */
|
|
if (session != IP_NULL)
|
|
ipcom_strcpy(session_id, session->session_id);
|
|
else
|
|
(void)ipdiameter_avp_get_session_id(ASR_package, session_id);
|
|
|
|
/* Add Session-Id AVP */
|
|
length = (Ip_u32)ipcom_strlen(session_id);
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_Session_Id,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL,
|
|
(Ip_u8 *)session_id, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_ASA: failed to add Session-Id AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Result-Code AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Result_Code,
|
|
0, IP_NULL, result_code);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_ASA: failed to add Result-Code AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_ASA: failed to add Origin-Host AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_ASA: failed to add Origin-Realm AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Optional: add User-Name AVP */
|
|
(void)ipdiameter_get_avp(ASR_package, DIAMETER_AVP_CODE_User_Name, &length, &user_name);
|
|
if (user_name != IP_NULL)
|
|
{
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_User_Name,
|
|
0, IP_NULL, user_name, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_ASA: failed to add User-Name AVP\n");
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/* Send the packet out */
|
|
if (session != IP_NULL)
|
|
retval = ipdiameter_session_pkt_send(session, message);
|
|
else
|
|
retval = ipdiameter_pkt_send(fd, ssl, message);
|
|
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_ASA: failed to send out ASA message\n");
|
|
|
|
out:
|
|
ipdiameter_answer_pkt_free(message);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_RAA
|
|
*===========================================================================
|
|
* Description: Complete a Re-Auth-Answer packet and send out
|
|
*
|
|
* 8.3.2. Re-Auth-Answer
|
|
*
|
|
* The Re-Auth-Answer (RAA), indicated by the Command-Code set to
|
|
* 258 and the message flags' 'R' bit clear, is sent in response to
|
|
* the RAR. The Result-Code AVP MUST be present, and indicates
|
|
* the disposition of the request.
|
|
*
|
|
* A successful RAA message MUST be followed by an application-specific
|
|
* authentication and/or authorization message.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <RAA> ::= < Diameter Header: 258, PXY >
|
|
* < Session-Id >
|
|
* { Result-Code }
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* [ User-Name ]
|
|
* [ Origin-State-Id ]
|
|
* [ Error-Message ]
|
|
* [ Error-Reporting-Host ]
|
|
* * [ Failed-AVP ]
|
|
* * [ Redirect-Host ]
|
|
* [ Redirect-Host-Usage ]
|
|
* [ Redirect-Max-Cache-Time ]
|
|
* * [ Proxy-Info ]
|
|
* * [ AVP ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_RAA(Ipdiameter_session *session, Ip_fd fd, SSL *ssl,
|
|
Ipdiameter_header *RAR_package, Ip_u32 result_code)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Ip_u8 *user_name = IP_NULL;
|
|
Ip_u8 *server_realm = IP_NULL;
|
|
char session_id[IPDIAMETER_MAX_SESSION_ID_SIZE] = IPDIAMETER_NULL_STRING;
|
|
|
|
|
|
message = ipdiameter_answer_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Re_Auth_Answer);
|
|
message->appl_id = RAR_package->appl_id;
|
|
message->hbh_id = RAR_package->hbh_id;
|
|
message->e2e_id = RAR_package->e2e_id;
|
|
|
|
/* Get Session-Id */
|
|
if (session != IP_NULL)
|
|
ipcom_strcpy(session_id, session->session_id);
|
|
else
|
|
(void)ipdiameter_avp_get_session_id(RAR_package, session_id);
|
|
|
|
/* Add Session-Id AVP */
|
|
length = (Ip_u32)ipcom_strlen(session_id);
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_Session_Id,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL,
|
|
(Ip_u8 *)session_id, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_RAA: failed to add Session-Id AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Result-Code AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Result_Code,
|
|
0, IP_NULL, result_code);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_RAA: failed to add Result-Code AVP\n"); goto out;
|
|
}
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_RAA: failed to add Origin-Host AVP\n"); goto out;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_RAA: failed to add Origin-Realm AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Optional: add User-Name AVP */
|
|
(void)ipdiameter_get_avp(RAR_package, DIAMETER_AVP_CODE_User_Name, &length, &user_name);
|
|
if (user_name != IP_NULL)
|
|
{
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_User_Name,
|
|
0, IP_NULL, user_name, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_RAA: failed to add User-Name AVP");
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/* Add Server-Realm AVP */
|
|
(void)ipdiameter_get_avp(RAR_package, DIAMETER_AVP_CODE_Origin_Realm,
|
|
&length, &server_realm);
|
|
if (server_realm != IP_NULL)
|
|
{
|
|
retval = ipdiameter_avp_add_array(message,
|
|
DIAMETER_AVP_CODE_Destination_Realm,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL,
|
|
server_realm, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_RAA: failed to add Server-Realm AVP");
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/* Send the packet out */
|
|
if (session != IP_NULL)
|
|
retval = ipdiameter_session_pkt_send(session, message);
|
|
else
|
|
retval = ipdiameter_pkt_send(fd, ssl, message);
|
|
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_RAA: failed to send out RAA message\n");
|
|
|
|
out:
|
|
ipdiameter_answer_pkt_free(message);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_STR
|
|
*===========================================================================
|
|
* Description: Complete a session termination request packet and send out
|
|
*
|
|
* 8.4.1. Session-Termination-Request
|
|
*
|
|
* The Session-Termination-Request (STR), indicated by the Command-Code
|
|
* set to 275 and the Command Flags' 'R' bit set, is sent by the access
|
|
* device to inform the Diameter Server that an authenticated and/or
|
|
* authorized session is being terminated.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <STR> ::= < Diameter Header: 275, REQ, PXY >
|
|
* < Session-Id >
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* { Destination-Realm }
|
|
* { Auth-Application-Id }
|
|
* { Termination-Cause }
|
|
* [ User-Name ]
|
|
* [ Destination-Host ]
|
|
* * [ Class ]
|
|
* [ Origin-State-Id ]
|
|
* * [ Proxy-Info ]
|
|
* * [ Route-Record ]
|
|
* * [ AVP ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_STR(Ipdiameter_session *session, Ip_u32 cause)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Ip_s8 index_v;
|
|
|
|
|
|
message = ipdiameter_request_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Session_Termination_Request);
|
|
#ifdef OPEN_DIAMETER_TEST
|
|
message->appl_id = (Ip_u32)ip_htonl(DIAMETER_Common_Message);
|
|
#else
|
|
message->appl_id = (Ip_u32)ip_htonl(session->appl_id);
|
|
#endif /* OPEN_DIAMETER_TEST */
|
|
message->hbh_id = ipdiameter_get_unique_id();
|
|
message->e2e_id = message->hbh_id;
|
|
|
|
/* Insert request into session's request list */
|
|
ipdiameter_session_add_req(session, (struct Ipdiameter_header *)message);
|
|
|
|
/* Add Session-Id AVP */
|
|
length = (Ip_u32)ipcom_strlen(session->session_id);
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_Session_Id,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL,
|
|
(Ip_u8 *)session->session_id, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_STR: failed to add Session-Id AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_STR: failed to add Origin-Host AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_STR: failed to add Origin-Realm AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Destination-Realm AVP */
|
|
index_v = session->selected_server;
|
|
length = (Ip_u32)ipcom_strlen(((Ipdiameter_server *)session->serv_list[index_v])->realm);
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_Destination_Realm,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL,
|
|
(Ip_u8 *)(((Ipdiameter_server *)session->serv_list[index_v])->realm),
|
|
length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_STR: failed to add Destination-Realm AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Auth-Application-Id AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Auth_Application_Id,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, session->appl_id);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_STR: failed to add Auth-Application-Id AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Termination-Cause AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Termination_Cause,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, cause);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_STR: failed to add Termination-Cause AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
|
|
/* Send the packet out */
|
|
retval = ipdiameter_session_pkt_send(session, message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_STR: failed to send out STR message\n");
|
|
goto err;
|
|
}
|
|
return retval;
|
|
|
|
err:
|
|
ipdiameter_request_pkt_free(message);
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_CER
|
|
*===========================================================================
|
|
* Description: Complete a capabilities exchange Request packet and send out
|
|
*
|
|
* 5.3.1. Capabilities-Exchange-Request
|
|
*
|
|
* The Capabilities-Exchange-Request (CER), indicated by the Command-
|
|
* Code set to 257 and the Command Flags' 'R' bit set, is sent to
|
|
* exchange local capabilities. Upon detection of a transport failure,
|
|
* this message MUST NOT be sent to an alternate peer.
|
|
*
|
|
* When Diameter is run over SCTP [SCTP], which allows for connections
|
|
* to span multiple interfaces and multiple IP addresses, the
|
|
* Capabilities-Exchange-Request message MUST contain one Host-IP-
|
|
* Address AVP for each potential IP address that MAY be locally used
|
|
* when transmitting Diameter messages.
|
|
*
|
|
*
|
|
* Message Format
|
|
*
|
|
* <CER> ::= < Diameter Header: 257, REQ >
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* 1* { Host-IP-Address }
|
|
* { Vendor-Id }
|
|
* { Product-Name }
|
|
* [ Origin-State-Id ]
|
|
* * [ Supported-Vendor-Id ]
|
|
* * [ Auth-Application-Id ]
|
|
* * [ Inband-Security-Id ]
|
|
* * [ Acct-Application-Id ]
|
|
* * [ Vendor-Specific-Application-Id ]
|
|
* [ Firmware-Revision ]
|
|
* * [ AVP ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_CER(Ipdiameter_peer_entry *peer)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
|
|
message = ipdiameter_request_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Capabilities_Exchange_Request);
|
|
message->appl_id = ip_htonl(DIAMETER_Common_Message);
|
|
message->hbh_id = ipdiameter_get_unique_id();
|
|
message->e2e_id = message->hbh_id;
|
|
|
|
/* Insert request into peer's request list */
|
|
ipdiameter_peer_add_req(peer, (struct Ipdiameter_header *)message);
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Origin-Host AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Origin-Realm AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Host-IP-Address AVP */
|
|
retval = ipdiameter_avp_add_host_address(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Host-IP-Address AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Vendor-Id AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Vendor_Id,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, ipdiameter.vendor_id);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Vendor-Id AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Product-Name AVP */
|
|
length = (Ip_u32)ipcom_strlen(IPDIAMETER_PRODUCT_NAME);
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_Product_Name,
|
|
0, IP_NULL, (Ip_u8 *)IPDIAMETER_PRODUCT_NAME, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Product-Name AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Application-Id AVPs */
|
|
retval = ipdiameter_avp_add_appl_ids(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Application-Id AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Send the packet out */
|
|
retval = ipdiameter_peer_pkt_send(peer, message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to send out CER message\n");
|
|
goto err;
|
|
}
|
|
return retval;
|
|
|
|
|
|
err:
|
|
ipdiameter_request_pkt_free(message);
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_CEA
|
|
*===========================================================================
|
|
* Description: Complete a capabilities exchange Answer packet and send out
|
|
*
|
|
* 5.3.2. Capabilities-Exchange-Answer
|
|
*
|
|
* The Capabilities-Exchange-Answer (CEA), indicated by the Command-Code
|
|
* set to 257 and the Command Flags' 'R' bit cleared, is sent in
|
|
* response to a CER message.
|
|
*
|
|
* When Diameter is run over SCTP [SCTP], which allows connections to
|
|
* span multiple interfaces, hence, multiple IP addresses, the
|
|
* Capabilities-Exchange-Answer message MUST contain one Host-IP-Address
|
|
* AVP for each potential IP address that MAY be locally used when
|
|
* transmitting Diameter messages.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <CEA> ::= < Diameter Header: 257 >
|
|
* { Result-Code }
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* 1* { Host-IP-Address }
|
|
* { Vendor-Id }
|
|
* { Product-Name }
|
|
* [ Origin-State-Id ]
|
|
* [ Error-Message ]
|
|
* * [ Failed-AVP ]
|
|
* * [ Supported-Vendor-Id ]
|
|
* * [ Auth-Application-Id ]
|
|
* * [ Inband-Security-Id ]
|
|
* * [ Acct-Application-Id ]
|
|
* * [ Vendor-Specific-Application-Id ]
|
|
* [ Firmware-Revision ]
|
|
* * [ AVP ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_CEA(Ipdiameter_peer_entry *peer, Ipdiameter_header *CER_package, Ip_u32 result_code)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
|
|
|
|
#ifdef DIAMETER_DEBUG
|
|
ipcom_printf("Calling ipdiameter_send_CEA\n");
|
|
#endif
|
|
|
|
message = ipdiameter_answer_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Capabilities_Exchange_Answer);
|
|
message->appl_id = ip_htonl(DIAMETER_Common_Message);
|
|
message->hbh_id = CER_package->hbh_id;
|
|
message->e2e_id = CER_package->e2e_id;
|
|
|
|
|
|
/* Add Result-Code AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Result_Code,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, result_code);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CEA: failed to add Result-Code AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CEA: failed to add Origin-Host AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CEA: failed to add Origin-Realm AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Host-IP-Address AVP */
|
|
retval = ipdiameter_avp_add_host_address(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CEA: failed to add Host-IP-Address AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Vendor-Id AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Vendor_Id,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, ipdiameter.vendor_id);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Vendor-Id AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Product-Name AVP */
|
|
length = (Ip_u32)ipcom_strlen(IPDIAMETER_PRODUCT_NAME);
|
|
retval = ipdiameter_avp_add_array(message, DIAMETER_AVP_CODE_Product_Name,
|
|
0, IP_NULL, (Ip_u8 *)IPDIAMETER_PRODUCT_NAME, length);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Product-Name AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Application-Id AVPs */
|
|
retval = ipdiameter_avp_add_appl_ids(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CER: failed to add Application-Id AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
|
|
/* Send the packet out */
|
|
retval = ipdiameter_peer_pkt_send(peer, message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_CEA: failed to send out CEA message\n");
|
|
|
|
out:
|
|
ipdiameter_answer_pkt_free(message);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_DWR
|
|
*===========================================================================
|
|
* Description: Complete a device watchdog request packet and send out
|
|
*
|
|
* 5.5.2. Device-Watchdog-Request
|
|
*
|
|
* The Device-Watchdog-Request (DWR), indicated by the Command-Code set
|
|
* to 280 and the Command Flags' 'R' bit set, is sent to a peer when no
|
|
* traffic has been exchanged between two peers (see Section 5.5.3).
|
|
* Upon detection of a transport failure, this message MUST NOT be sent
|
|
* to an alternate peer.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <DWR> ::= < Diameter Header: 280, REQ >
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* [ Origin-State-Id ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_DWR(Ipdiameter_peer_entry *peer)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
|
|
message = ipdiameter_request_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Device_Watchdog_Request);
|
|
message->appl_id = ip_htonl(DIAMETER_Common_Message);
|
|
message->hbh_id = ipdiameter_get_unique_id();
|
|
message->e2e_id = message->hbh_id;
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DWR: failed to add Origin-Host AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DWR: failed to add Origin-Realm AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
|
|
/* Send the packet out */
|
|
retval = ipdiameter_peer_pkt_send(peer, message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DWR: failed to send out DWR message\n");
|
|
|
|
out:
|
|
ipdiameter_request_pkt_free(message);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_DWA
|
|
*===========================================================================
|
|
* Description: Complete a device watchdog answer packet and send out
|
|
*
|
|
* 5.5.2. Device-Watchdog-Answer
|
|
*
|
|
* The Device-Watchdog-Answer (DWA), indicated by the Command-Code set
|
|
* to 280 and the Command Flags' 'R' bit cleared, is sent as a response
|
|
* to the Device-Watchdog-Request message.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <DWA> ::= < Diameter Header: 280 >
|
|
* { Result-Code }
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* [ Error-Message ]
|
|
* * [ Failed-AVP ]
|
|
* [ Original-State-Id ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_DWA(Ipdiameter_peer_entry *peer, Ipdiameter_header *DWR_package, Ip_u32 result_code)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
|
|
|
|
message = ipdiameter_answer_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Device_Watchdog_Answer);
|
|
message->appl_id = ip_htonl(DIAMETER_Common_Message);
|
|
message->hbh_id = DWR_package->hbh_id;
|
|
message->e2e_id = DWR_package->e2e_id;
|
|
|
|
/* Add Result-Code AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Result_Code,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, result_code);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DWA: failed to add Result-Code AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DWA: failed to add Origin-Host AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DWA: failed to add Origin-Realm AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
|
|
/* Send the packet out */
|
|
retval = ipdiameter_peer_pkt_send(peer, message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DWA: failed to send out DWA message\n");
|
|
|
|
out:
|
|
ipdiameter_answer_pkt_free(message);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_DPR
|
|
*===========================================================================
|
|
* Description: Complete a disconnect peer request packet and send out
|
|
*
|
|
* 5.4.1. Disconnect-Peer-Request
|
|
*
|
|
* The Disconnect-Peer-Request (DPR), indicated by the Command-Code set
|
|
* to 282 and the Command Flags' 'R' bit set, is sent to a peer to
|
|
* inform its intentions to shutdown the transport connection. Upon
|
|
* detection of a transport failure, this message MUST NOT be sent to an
|
|
* alternate peer.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <DPR> ::= < Diameter Header: 282, REQ >
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* { Disconnect-Cause }
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_DPR(Ipdiameter_peer_entry *peer, Ip_u32 cause)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
|
|
message = ipdiameter_request_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Disconnect_Peer_Request);
|
|
message->appl_id = ip_htonl(DIAMETER_Common_Message);
|
|
message->hbh_id = ipdiameter_get_unique_id();
|
|
message->e2e_id = message->hbh_id;
|
|
|
|
/* Insert request into peer's request list */
|
|
ipdiameter_peer_add_req(peer, (struct Ipdiameter_header *)message);
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DPR: failed to add Origin-Host AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_ASA: failed to add Origin-Realm AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Add Disconnect-Cause AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Disconnect_Cause,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, cause);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DPR: failed to add Disconnect-Cause AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
/* Send the packet out */
|
|
retval = ipdiameter_peer_pkt_send(peer, message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DPR: failed to send out DPR message\n");
|
|
goto err;
|
|
}
|
|
|
|
return retval;
|
|
|
|
err:
|
|
ipdiameter_request_pkt_free(message);
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdiameter_send_DPA
|
|
*===========================================================================
|
|
* Description: Complete a disconnect peer answer packet and send out
|
|
*
|
|
* 5.4.2. Disconnect-Peer-Answer
|
|
*
|
|
* The Disconnect-Peer-Answer (DPA), indicated by the Command-Code set
|
|
* to 282 and the Command Flags' 'R' bit cleared, is sent as a response
|
|
* to the Disconnect-Peer-Request message. Upon receipt of this
|
|
* message, the transport connection is shutdown.
|
|
*
|
|
* Message Format
|
|
*
|
|
* <DPA> ::= < Diameter Header: 282 >
|
|
* { Result-Code }
|
|
* { Origin-Host }
|
|
* { Origin-Realm }
|
|
* [ Error-Message ]
|
|
* * [ Failed-AVP ]
|
|
*
|
|
* Parameters:
|
|
* Returns: result
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdiameter_send_DPA(Ipdiameter_peer_entry *peer, Ipdiameter_header *DPR_package, Ip_u32 result_code)
|
|
{
|
|
Ipdiameter_header *message;
|
|
Ip_u32 length = 0;
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
|
|
|
|
message = ipdiameter_answer_pkt_malloc(length);
|
|
if(message == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
ipdiameter_set_hdr_code((Ip_u32 *)message, DIAMETER_CODE_Disconnect_Peer_Answer);
|
|
message->appl_id = ip_htonl(DIAMETER_Common_Message);
|
|
message->hbh_id = DPR_package->hbh_id;
|
|
message->e2e_id = DPR_package->e2e_id;
|
|
|
|
/* Add Result-Code AVP */
|
|
retval = ipdiameter_avp_add_u32(message, DIAMETER_AVP_CODE_Result_Code,
|
|
DIAMETER_AVP_M_FLAG, IP_NULL, result_code);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DPA: failed to add Result-Code AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Host AVP */
|
|
retval = ipdiameter_avp_add_origin_host(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DPA: failed to add Origin-Host AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
/* Add Origin-Realm AVP */
|
|
retval = ipdiameter_avp_add_origin_realm(message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DPA: failed to add Origin-Realm AVP\n");
|
|
goto out;
|
|
}
|
|
|
|
|
|
/* Send the packet out */
|
|
retval = ipdiameter_peer_pkt_send(peer, message);
|
|
if (retval != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "ipdiameter_send_DPA: failed to send out DPA message\n");
|
|
|
|
out:
|
|
ipdiameter_answer_pkt_free(message);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|