2017-11-24 15:04:45 +00:00
|
|
|
#define TRACE_MODULE _s1ap_sctp
|
2017-10-18 16:09:06 +00:00
|
|
|
|
|
|
|
#include "core_debug.h"
|
2017-11-23 10:44:49 +00:00
|
|
|
#include "core_thread.h"
|
2017-10-18 16:09:06 +00:00
|
|
|
|
|
|
|
#include "mme_event.h"
|
|
|
|
|
|
|
|
#include "s1ap_path.h"
|
|
|
|
|
2017-11-24 15:04:45 +00:00
|
|
|
#if HAVE_NETDB_H
|
|
|
|
#include <netdb.h>
|
|
|
|
#endif
|
|
|
|
|
2017-10-18 16:09:06 +00:00
|
|
|
#if HAVE_USRSCTP_H
|
2017-10-19 03:50:39 +00:00
|
|
|
#ifndef INET
|
|
|
|
#define INET 1
|
|
|
|
#endif
|
|
|
|
#ifndef INET6
|
|
|
|
#define INET6 1
|
|
|
|
#endif
|
2017-10-18 16:09:06 +00:00
|
|
|
#include <usrsctp.h>
|
|
|
|
#endif
|
|
|
|
|
2017-11-24 13:02:40 +00:00
|
|
|
static status_t s1ap_usrsctp_socket(sock_id *new,
|
|
|
|
int family, int type,
|
|
|
|
int (*receive_cb)(struct socket *sock, union sctp_sockstore addr,
|
|
|
|
void *data, size_t datalen, struct sctp_rcvinfo, int flags,
|
|
|
|
void *ulp_info));
|
|
|
|
static status_t s1ap_usrsctp_bind(sock_id id, c_sockaddr_t *sa);
|
|
|
|
static status_t s1ap_usrsctp_connect(sock_id id, c_sockaddr_t *sa);
|
|
|
|
static status_t s1ap_usrsctp_listen(sock_id id);
|
|
|
|
|
2017-11-24 15:04:45 +00:00
|
|
|
static int s1ap_usrsctp_recv_handler(struct socket *sock,
|
2017-10-18 16:09:06 +00:00
|
|
|
union sctp_sockstore addr, void *data, size_t datalen,
|
|
|
|
struct sctp_rcvinfo rcv, int flags, void *ulp_info);
|
|
|
|
|
2017-11-24 13:02:40 +00:00
|
|
|
static c_sockaddr_t *usrsctp_remote_addr(union sctp_sockstore *store);
|
2017-10-18 16:09:06 +00:00
|
|
|
static void debug_printf(const char *format, ...);
|
|
|
|
|
2017-11-23 14:01:49 +00:00
|
|
|
status_t s1ap_init(c_uint16_t port)
|
2017-10-18 16:09:06 +00:00
|
|
|
{
|
2017-11-23 14:01:49 +00:00
|
|
|
usrsctp_init(port, NULL, debug_printf);
|
|
|
|
#ifdef SCTP_DEBUG
|
|
|
|
usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
|
|
|
|
#endif
|
|
|
|
usrsctp_sysctl_set_sctp_blackhole(2);
|
|
|
|
usrsctp_sysctl_set_sctp_enable_sack_immediately(1);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t s1ap_final()
|
|
|
|
{
|
|
|
|
while(usrsctp_finish() != 0)
|
|
|
|
{
|
|
|
|
d_error("try to finsih SCTP\n");
|
|
|
|
core_sleep(time_from_msec(1000));
|
|
|
|
}
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-10-18 16:09:06 +00:00
|
|
|
|
2017-11-24 15:04:45 +00:00
|
|
|
status_t s1ap_delete(sock_id sock)
|
|
|
|
{
|
|
|
|
d_assert(sock, return CORE_ERROR,);
|
|
|
|
usrsctp_close((struct socket *)sock);
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-12-08 05:29:35 +00:00
|
|
|
status_t s1ap_server(sock_node_t *snode, int type)
|
|
|
|
{
|
|
|
|
status_t rv;
|
|
|
|
char buf[CORE_ADDRSTRLEN];
|
|
|
|
|
|
|
|
d_assert(snode, return CORE_ERROR,);
|
|
|
|
|
|
|
|
rv = sctp_server(&snode->sock, type, snode->list);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
|
|
|
|
|
|
|
d_trace(1, "s1ap_server() [%s]:%d\n",
|
|
|
|
CORE_ADDR(snode->list, buf), CORE_PORT(snode->list));
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t sctp_server(sock_id *new, int type, c_sockaddr_t *sa_list)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
|
|
|
status_t rv;
|
2017-12-08 03:43:35 +00:00
|
|
|
c_sockaddr_t *addr;
|
2017-11-24 13:02:40 +00:00
|
|
|
char buf[CORE_ADDRSTRLEN];
|
|
|
|
|
2017-12-08 03:43:35 +00:00
|
|
|
addr = sa_list;
|
|
|
|
while(addr)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
|
|
|
rv = s1ap_usrsctp_socket(new,
|
2017-12-08 03:43:35 +00:00
|
|
|
addr->c_sa_family, type, s1ap_usrsctp_recv_handler);
|
2018-01-04 13:03:59 +00:00
|
|
|
if (rv == CORE_OK)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
2018-01-04 13:03:59 +00:00
|
|
|
if (s1ap_usrsctp_bind(*new, addr) == CORE_OK)
|
|
|
|
{
|
2018-01-23 08:11:21 +00:00
|
|
|
d_trace(9, "sctp_server [%s]:%d\n",
|
2018-01-04 13:03:59 +00:00
|
|
|
CORE_ADDR(addr, buf), CORE_PORT(addr));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = s1ap_delete(*new);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
2017-11-24 13:02:40 +00:00
|
|
|
}
|
|
|
|
|
2017-12-08 03:43:35 +00:00
|
|
|
addr = addr->next;
|
2017-11-24 13:02:40 +00:00
|
|
|
}
|
|
|
|
|
2017-12-08 03:43:35 +00:00
|
|
|
if (addr == NULL)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
2017-12-08 05:48:48 +00:00
|
|
|
d_error("sctp_server [%s]:%d failed",
|
2017-12-08 03:43:35 +00:00
|
|
|
CORE_ADDR(addr, buf), CORE_PORT(addr));
|
2017-11-24 13:02:40 +00:00
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = s1ap_usrsctp_listen(*new);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-12-08 05:29:35 +00:00
|
|
|
status_t sctp_client(sock_id *new, int type, c_sockaddr_t *sa_list)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
|
|
|
status_t rv;
|
2017-12-08 03:43:35 +00:00
|
|
|
c_sockaddr_t *addr;
|
2017-11-24 13:02:40 +00:00
|
|
|
char buf[CORE_ADDRSTRLEN];
|
|
|
|
|
2017-12-08 05:29:35 +00:00
|
|
|
addr = sa_list;
|
2017-12-08 03:43:35 +00:00
|
|
|
while(addr)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
2017-12-08 03:43:35 +00:00
|
|
|
rv = s1ap_usrsctp_socket(new, addr->c_sa_family, type, NULL);
|
2018-01-04 13:03:59 +00:00
|
|
|
if (rv == CORE_OK)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
2018-01-04 13:03:59 +00:00
|
|
|
if (s1ap_usrsctp_connect(*new, addr) == CORE_OK)
|
|
|
|
{
|
2018-01-23 08:11:21 +00:00
|
|
|
d_trace(9, "sctp_client [%s]:%d\n",
|
2018-01-04 13:03:59 +00:00
|
|
|
CORE_ADDR(addr, buf), CORE_PORT(addr));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = s1ap_delete(*new);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
2017-11-24 13:02:40 +00:00
|
|
|
}
|
|
|
|
|
2017-12-08 03:43:35 +00:00
|
|
|
addr = addr->next;
|
2017-11-24 13:02:40 +00:00
|
|
|
}
|
|
|
|
|
2017-12-08 03:43:35 +00:00
|
|
|
if (addr == NULL)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
2017-12-08 05:48:48 +00:00
|
|
|
d_error("sctp_client [%s]:%d failed",
|
2017-12-08 03:43:35 +00:00
|
|
|
CORE_ADDR(addr, buf), CORE_PORT(addr));
|
2017-11-24 13:02:40 +00:00
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-24 15:04:45 +00:00
|
|
|
status_t s1ap_send(sock_id id, pkbuf_t *pkbuf, c_sockaddr_t *addr)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
2017-11-24 15:04:45 +00:00
|
|
|
ssize_t sent;
|
|
|
|
struct socket *sock = (struct socket *)id;
|
|
|
|
struct sctp_sndinfo sndinfo;
|
2017-11-24 13:02:40 +00:00
|
|
|
|
2017-11-24 15:04:45 +00:00
|
|
|
d_assert(id, return CORE_ERROR, "Null param");
|
|
|
|
d_assert(pkbuf, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
memset((void *)&sndinfo, 0, sizeof(struct sctp_sndinfo));
|
|
|
|
sndinfo.snd_ppid = htonl(SCTP_S1AP_PPID);
|
|
|
|
sent = usrsctp_sendv(sock, pkbuf->payload, pkbuf->len,
|
|
|
|
addr ? &addr->sa : NULL, addr ? 1 : 0,
|
|
|
|
(void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo),
|
|
|
|
SCTP_SENDV_SNDINFO, 0);
|
|
|
|
|
2018-01-23 07:48:40 +00:00
|
|
|
d_trace(50, "[S1AP] SEND[%d] : ", sent);
|
2018-01-23 07:10:46 +00:00
|
|
|
d_trace_hex(50, pkbuf->payload, pkbuf->len);
|
2017-11-24 15:04:45 +00:00
|
|
|
if (sent < 0 || sent != pkbuf->len)
|
2017-11-24 13:02:40 +00:00
|
|
|
{
|
2017-11-24 15:04:45 +00:00
|
|
|
d_error("sent : %d, pkbuf->len : %d\n", sent, pkbuf->len);
|
2017-11-24 13:02:40 +00:00
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
2017-11-24 15:04:45 +00:00
|
|
|
pkbuf_free(pkbuf);
|
2017-11-24 13:02:40 +00:00
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t s1ap_recv(sock_id id, pkbuf_t *pkbuf)
|
|
|
|
{
|
|
|
|
struct socket *sock = (struct socket *)id;
|
2017-11-25 00:58:04 +00:00
|
|
|
c_sockaddr_t addr;
|
2017-11-24 13:02:40 +00:00
|
|
|
ssize_t n = 0;
|
|
|
|
int flags = 0;
|
|
|
|
socklen_t from_len;
|
|
|
|
socklen_t infolen;
|
|
|
|
struct sctp_rcvinfo rcv_info;
|
|
|
|
unsigned int infotype = 0;
|
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
n = usrsctp_recvv(sock, pkbuf->payload, MAX_SDU_LEN,
|
2017-11-25 00:58:04 +00:00
|
|
|
&addr.sa, &from_len, (void *)&rcv_info,
|
2017-11-24 13:02:40 +00:00
|
|
|
&infolen, &infotype, &flags);
|
|
|
|
if (n > 0)
|
|
|
|
{
|
|
|
|
#undef MSG_NOTIFICATION
|
|
|
|
#define MSG_NOTIFICATION 0x2000
|
|
|
|
if (flags & MSG_NOTIFICATION)
|
|
|
|
{
|
|
|
|
/* Nothing to do */
|
|
|
|
}
|
|
|
|
else if (flags & MSG_EOR)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pkbuf->len = n;
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static status_t s1ap_usrsctp_socket(sock_id *new,
|
2017-11-23 14:01:49 +00:00
|
|
|
int family, int type,
|
2017-11-25 00:58:04 +00:00
|
|
|
int (*receive_cb)(struct socket *sock, union sctp_sockstore store,
|
2017-11-23 14:01:49 +00:00
|
|
|
void *data, size_t datalen, struct sctp_rcvinfo, int flags,
|
|
|
|
void *ulp_info))
|
|
|
|
{
|
|
|
|
struct socket *sock = NULL;
|
2017-10-19 04:42:07 +00:00
|
|
|
const int on = 1;
|
|
|
|
struct sctp_event event;
|
|
|
|
c_uint16_t event_types[] = {
|
2017-10-19 03:50:39 +00:00
|
|
|
SCTP_ASSOC_CHANGE,
|
|
|
|
SCTP_PEER_ADDR_CHANGE,
|
|
|
|
SCTP_REMOTE_ERROR,
|
|
|
|
SCTP_SHUTDOWN_EVENT,
|
|
|
|
SCTP_ADAPTATION_INDICATION,
|
|
|
|
SCTP_PARTIAL_DELIVERY_EVENT
|
|
|
|
};
|
2017-10-19 04:42:07 +00:00
|
|
|
int i;
|
2017-10-18 16:09:06 +00:00
|
|
|
|
2017-11-23 14:01:49 +00:00
|
|
|
if (!(sock = usrsctp_socket(family, type, IPPROTO_SCTP,
|
|
|
|
receive_cb, NULL, 0, NULL)))
|
2017-10-18 16:09:06 +00:00
|
|
|
{
|
|
|
|
d_error("usrsctp_socket failed");
|
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
|
|
|
|
2017-11-23 14:01:49 +00:00
|
|
|
if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO,
|
2017-10-19 03:50:39 +00:00
|
|
|
&on, sizeof(int)) < 0)
|
|
|
|
{
|
2017-10-20 04:18:58 +00:00
|
|
|
d_error("usrsctp_setsockopt SCTP_RECVRCVINFO failed");
|
2017-10-19 03:50:39 +00:00
|
|
|
return CORE_ERROR;
|
2017-10-19 04:42:07 +00:00
|
|
|
}
|
2017-10-19 03:50:39 +00:00
|
|
|
|
2017-10-19 04:42:07 +00:00
|
|
|
memset(&event, 0, sizeof(event));
|
|
|
|
event.se_assoc_id = SCTP_FUTURE_ASSOC;
|
|
|
|
event.se_on = 1;
|
|
|
|
for (i = 0; i < (int)(sizeof(event_types)/sizeof(c_uint16_t)); i++)
|
2017-10-19 03:50:39 +00:00
|
|
|
{
|
2017-10-19 04:42:07 +00:00
|
|
|
event.se_type = event_types[i];
|
2017-11-23 14:01:49 +00:00
|
|
|
if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT,
|
2017-10-19 03:50:39 +00:00
|
|
|
&event, sizeof(struct sctp_event)) < 0)
|
|
|
|
{
|
2017-10-20 04:18:58 +00:00
|
|
|
d_error("usrsctp_setsockopt SCTP_EVENT failed");
|
2017-10-19 03:50:39 +00:00
|
|
|
return CORE_ERROR;
|
2017-10-19 04:42:07 +00:00
|
|
|
}
|
|
|
|
}
|
2017-10-19 03:50:39 +00:00
|
|
|
|
2017-11-23 14:01:49 +00:00
|
|
|
*new = (sock_id)sock;
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-24 13:02:40 +00:00
|
|
|
static status_t s1ap_usrsctp_bind(sock_id id, c_sockaddr_t *sa)
|
2017-11-23 14:01:49 +00:00
|
|
|
{
|
|
|
|
struct socket *sock = (struct socket *)id;
|
|
|
|
char buf[CORE_ADDRSTRLEN];
|
|
|
|
socklen_t addrlen;
|
|
|
|
|
|
|
|
d_assert(sock, return CORE_ERROR,);
|
|
|
|
d_assert(sa, return CORE_ERROR,);
|
|
|
|
|
|
|
|
addrlen = sockaddr_len(sa);
|
|
|
|
d_assert(addrlen, return CORE_ERROR,);
|
2017-10-18 16:09:06 +00:00
|
|
|
|
2017-11-23 14:01:49 +00:00
|
|
|
if (usrsctp_bind(sock, &sa->sa, addrlen) != 0)
|
2017-10-18 16:09:06 +00:00
|
|
|
{
|
2017-11-24 15:52:07 +00:00
|
|
|
d_error("usrsctp_bind [%s]:%d failed",
|
2017-11-25 14:28:34 +00:00
|
|
|
CORE_ADDR(sa, buf), CORE_PORT(sa));
|
2017-10-18 16:09:06 +00:00
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
|
|
|
|
2018-01-23 08:11:21 +00:00
|
|
|
d_trace(9, "usrsctp_bind [%s]:%d\n", CORE_ADDR(sa, buf), CORE_PORT(sa));
|
2017-11-23 14:01:49 +00:00
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-24 13:02:40 +00:00
|
|
|
static status_t s1ap_usrsctp_connect(sock_id id, c_sockaddr_t *sa)
|
2017-11-23 14:01:49 +00:00
|
|
|
{
|
|
|
|
struct socket *sock = (struct socket *)id;
|
|
|
|
char buf[CORE_ADDRSTRLEN];
|
|
|
|
socklen_t addrlen;
|
|
|
|
|
|
|
|
d_assert(sock, return CORE_ERROR,);
|
|
|
|
d_assert(sa, return CORE_ERROR,);
|
|
|
|
|
|
|
|
addrlen = sockaddr_len(sa);
|
|
|
|
d_assert(addrlen, return CORE_ERROR,);
|
|
|
|
|
|
|
|
if (usrsctp_connect(sock, &sa->sa, addrlen) != 0)
|
2017-10-18 16:09:06 +00:00
|
|
|
{
|
2017-11-25 14:28:34 +00:00
|
|
|
d_error("usrsctp_connect [%s]:%d", CORE_ADDR(sa, buf), CORE_PORT(sa));
|
2017-10-18 16:09:06 +00:00
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
|
|
|
|
2018-01-23 08:11:21 +00:00
|
|
|
d_trace(9, "usrsctp_connect [%s]:%d\n", CORE_ADDR(sa, buf), CORE_PORT(sa));
|
2017-10-18 16:09:06 +00:00
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-24 13:02:40 +00:00
|
|
|
static status_t s1ap_usrsctp_listen(sock_id id)
|
2017-10-18 16:09:06 +00:00
|
|
|
{
|
2017-11-23 14:01:49 +00:00
|
|
|
int rc;
|
|
|
|
struct socket *sock = (struct socket *)id;
|
|
|
|
d_assert(sock, return CORE_ERROR,);
|
|
|
|
|
|
|
|
rc = usrsctp_listen(sock, 5);
|
|
|
|
if (rc < 0)
|
2017-10-20 04:18:58 +00:00
|
|
|
{
|
2017-11-23 14:01:49 +00:00
|
|
|
d_error("usrsctp_listen failed");
|
|
|
|
return CORE_ERROR;
|
2017-10-20 04:18:58 +00:00
|
|
|
}
|
2017-11-23 14:01:49 +00:00
|
|
|
|
2017-10-20 07:32:57 +00:00
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-24 15:04:45 +00:00
|
|
|
static int s1ap_usrsctp_recv_handler(struct socket *sock,
|
2017-11-25 00:58:04 +00:00
|
|
|
union sctp_sockstore store, void *data, size_t datalen,
|
2017-10-20 04:18:58 +00:00
|
|
|
struct sctp_rcvinfo rcv, int flags, void *ulp_info)
|
|
|
|
{
|
2017-10-20 06:52:30 +00:00
|
|
|
if (data)
|
2017-10-20 06:46:06 +00:00
|
|
|
{
|
2017-11-23 12:05:55 +00:00
|
|
|
event_t e;
|
|
|
|
|
|
|
|
#undef MSG_NOTIFICATION
|
|
|
|
#define MSG_NOTIFICATION 0x2000
|
2017-10-20 06:46:06 +00:00
|
|
|
if (flags & MSG_NOTIFICATION)
|
|
|
|
{
|
2017-11-23 12:05:55 +00:00
|
|
|
union sctp_notification *not = (union sctp_notification *)data;
|
|
|
|
if (not->sn_header.sn_length == (c_uint32_t)datalen)
|
|
|
|
{
|
|
|
|
switch(not->sn_header.sn_type)
|
|
|
|
{
|
|
|
|
case SCTP_ASSOC_CHANGE :
|
2018-01-23 08:11:21 +00:00
|
|
|
d_trace(9, "SCTP_ASSOC_CHANGE"
|
2017-11-23 12:05:55 +00:00
|
|
|
"(type:0x%x, flags:0x%x, state:0x%x)\n",
|
|
|
|
not->sn_assoc_change.sac_type,
|
|
|
|
not->sn_assoc_change.sac_flags,
|
|
|
|
not->sn_assoc_change.sac_state);
|
|
|
|
|
|
|
|
if (not->sn_assoc_change.sac_state ==
|
|
|
|
SCTP_SHUTDOWN_COMP ||
|
|
|
|
not->sn_assoc_change.sac_state ==
|
|
|
|
SCTP_COMM_LOST)
|
|
|
|
{
|
2017-11-25 00:58:04 +00:00
|
|
|
c_sockaddr_t *addr =
|
|
|
|
usrsctp_remote_addr(&store);
|
|
|
|
d_assert(addr, return 1,);
|
2017-11-24 02:49:37 +00:00
|
|
|
|
2017-11-23 12:05:55 +00:00
|
|
|
event_set(&e, MME_EVT_S1AP_LO_CONNREFUSED);
|
|
|
|
event_set_param1(&e, (c_uintptr_t)sock);
|
2017-11-25 00:58:04 +00:00
|
|
|
event_set_param2(&e, (c_uintptr_t)addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
if (mme_event_send(&e) != CORE_OK)
|
|
|
|
{
|
2018-01-13 13:03:30 +00:00
|
|
|
CORE_FREE(addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
}
|
2017-11-23 12:05:55 +00:00
|
|
|
}
|
2017-11-24 02:49:37 +00:00
|
|
|
else if (not->sn_assoc_change.sac_state == SCTP_COMM_UP)
|
|
|
|
{
|
2017-11-25 00:58:04 +00:00
|
|
|
c_sockaddr_t *addr =
|
|
|
|
usrsctp_remote_addr(&store);
|
|
|
|
d_assert(addr, return 1,);
|
2017-11-23 12:05:55 +00:00
|
|
|
|
2017-11-24 02:49:37 +00:00
|
|
|
event_set(&e, MME_EVT_S1AP_LO_ACCEPT);
|
|
|
|
event_set_param1(&e, (c_uintptr_t)sock);
|
2017-11-25 00:58:04 +00:00
|
|
|
event_set_param2(&e, (c_uintptr_t)addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
if (mme_event_send(&e) != CORE_OK)
|
|
|
|
{
|
2018-01-13 13:03:30 +00:00
|
|
|
CORE_FREE(addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
}
|
|
|
|
}
|
2017-11-23 12:05:55 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
case SCTP_PEER_ADDR_CHANGE:
|
|
|
|
break;
|
|
|
|
case SCTP_SEND_FAILED :
|
|
|
|
d_error("SCTP_SEND_FAILED"
|
|
|
|
"(type:0x%x, flags:0x%x, error:0x%x)\n",
|
|
|
|
not->sn_send_failed_event.ssfe_type,
|
|
|
|
not->sn_send_failed_event.ssfe_flags,
|
|
|
|
not->sn_send_failed_event.ssfe_error);
|
|
|
|
break;
|
|
|
|
case SCTP_SHUTDOWN_EVENT :
|
2017-11-24 02:49:37 +00:00
|
|
|
{
|
2017-11-25 00:58:04 +00:00
|
|
|
c_sockaddr_t *addr = usrsctp_remote_addr(&store);
|
|
|
|
d_assert(addr, return 1,);
|
2017-11-24 02:49:37 +00:00
|
|
|
|
2017-11-23 12:05:55 +00:00
|
|
|
event_set(&e, MME_EVT_S1AP_LO_CONNREFUSED);
|
|
|
|
event_set_param1(&e, (c_uintptr_t)sock);
|
2017-11-25 00:58:04 +00:00
|
|
|
event_set_param2(&e, (c_uintptr_t)addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
if (mme_event_send(&e) != CORE_OK)
|
|
|
|
{
|
2018-01-13 13:03:30 +00:00
|
|
|
CORE_FREE(addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
}
|
2017-11-23 12:05:55 +00:00
|
|
|
break;
|
2017-11-24 02:49:37 +00:00
|
|
|
}
|
2017-11-23 12:05:55 +00:00
|
|
|
default :
|
|
|
|
d_error("Discarding event with unknown "
|
|
|
|
"flags = 0x%x, type 0x%x",
|
|
|
|
flags, not->sn_header.sn_type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 06:46:06 +00:00
|
|
|
}
|
2017-11-23 12:05:55 +00:00
|
|
|
else if (flags & MSG_EOR)
|
2017-10-20 06:46:06 +00:00
|
|
|
{
|
2017-11-23 12:05:55 +00:00
|
|
|
pkbuf_t *pkbuf;
|
2017-11-25 00:58:04 +00:00
|
|
|
c_sockaddr_t *addr = NULL;
|
2017-10-20 04:18:58 +00:00
|
|
|
|
2017-11-23 12:05:55 +00:00
|
|
|
pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
|
|
|
d_assert(pkbuf, return 1, );
|
2017-11-25 00:58:04 +00:00
|
|
|
addr = usrsctp_remote_addr(&store);
|
|
|
|
d_assert(addr, return 1,);
|
2017-10-20 04:18:58 +00:00
|
|
|
|
2017-11-23 12:05:55 +00:00
|
|
|
pkbuf->len = datalen;
|
|
|
|
memcpy(pkbuf->payload, data, pkbuf->len);
|
2017-10-20 04:18:58 +00:00
|
|
|
|
2018-01-23 07:48:40 +00:00
|
|
|
d_trace(50, "[S1AP] RECV : ");
|
|
|
|
d_trace_hex(50, pkbuf->payload, pkbuf->len);
|
|
|
|
|
2017-11-23 12:05:55 +00:00
|
|
|
event_set(&e, MME_EVT_S1AP_MESSAGE);
|
|
|
|
event_set_param1(&e, (c_uintptr_t)sock);
|
2017-11-25 00:58:04 +00:00
|
|
|
event_set_param2(&e, (c_uintptr_t)addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
event_set_param3(&e, (c_uintptr_t)pkbuf);
|
|
|
|
if (mme_event_send(&e) != CORE_OK)
|
|
|
|
{
|
|
|
|
pkbuf_free(pkbuf);
|
2018-01-13 13:03:30 +00:00
|
|
|
CORE_FREE(addr);
|
2017-11-24 02:49:37 +00:00
|
|
|
}
|
2017-11-23 12:05:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d_error("Not engough buffer. Need more recv : 0x%x", flags);
|
2017-10-20 04:18:58 +00:00
|
|
|
}
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
2017-11-24 13:02:40 +00:00
|
|
|
static c_sockaddr_t *usrsctp_remote_addr(union sctp_sockstore *store)
|
|
|
|
{
|
|
|
|
c_sockaddr_t *addr = NULL;
|
|
|
|
|
|
|
|
d_assert(store, return NULL,);
|
|
|
|
|
|
|
|
addr = core_calloc(1, sizeof(c_sockaddr_t));
|
|
|
|
d_assert(addr, return NULL,);
|
|
|
|
|
|
|
|
addr->c_sa_family = store->sin.sin_family;
|
|
|
|
switch(addr->c_sa_family)
|
|
|
|
{
|
|
|
|
case AF_INET:
|
|
|
|
memcpy(&addr->sin, &store->sin, sizeof(struct sockaddr_in));
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
memcpy(&addr->sin6, &store->sin6, sizeof(struct sockaddr_in6));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
d_assert(0, return NULL,);
|
|
|
|
}
|
|
|
|
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
2017-10-18 16:09:06 +00:00
|
|
|
static void debug_printf(const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
vprintf(format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|