59 #define LOG_PREFIX "sigtran"
61 #include <osmocom/core/talloc.h>
63 #include <freeradius-devel/server/base.h>
64 #include <freeradius-devel/util/debug.h>
65 #include <freeradius-devel/io/schedule.h>
67 #include <semaphore.h>
70 #include <osmocom/core/logging.h>
71 #include <osmocom/sccp/sccp_types.h>
72 #include <osmocom/mtp/mtp_level3.h>
74 #include "libosmo-m3ua/include/bsc_data.h"
75 #include "libosmo-m3ua/include/sctp_m3ua.h"
83 typedef int (*
osmo_cb_func)(
struct osmo_fd *fd,
unsigned int what);
92 osmo_fd_unregister(ofd);
113 MEM(ofd = talloc_zero(ctx,
struct osmo_fd));
115 ofd->when = BSC_FD_READ;
118 if (osmo_fd_register(ofd) < 0) {
119 ERROR(
"Failed registering pipe %i", fd);
132 mtp3_link->shutdown(mtp3_link);
140 struct mtp_m3ua_client_link *client,
143 struct mtp_m3ua_reg_req *route;
147 route = mtp_m3ua_reg_req_add(client);
148 if (!route)
return -1;
150 route->dpc =
conf->dpc;
153 struct mtp_m3ua_opc *opc;
155 for (i = 0; i < talloc_array_length(
conf->opc); i++) {
156 opc = talloc_zero(route,
struct mtp_m3ua_opc);
157 opc->opc =
conf->opc[i];
158 llist_add_tail(&opc->list, &route->opc);
163 struct mtp_m3ua_si *si;
165 for (i = 0; i < talloc_array_length(
conf->si); i++) {
166 si = talloc_zero(route,
struct mtp_m3ua_si);
167 si->si =
conf->si[i];
168 llist_add_tail(&si->list, &route->si);
190 struct mtp_link_set *mtp3_link_set;
191 struct mtp_link *mtp3_link;
192 struct mtp_m3ua_client_link *m3ua_client;
202 conn->
bsc_data = bsc_data_alloc(conn);
203 talloc_set_destructor(conn, _conn_free);
205 conn->
bsc_data = bsc_data_alloc(ctx);
212 mtp3_link_set->dpc =
conf->mtp3_dpc;
213 mtp3_link_set->opc =
conf->mtp3_opc;
221 MEM(mtp3_link = conn->
mtp3_link = mtp_link_alloc(mtp3_link_set));
223 mtp3_link->name = talloc_strdup(mtp3_link,
"default");
229 MEM(m3ua_client = mtp3_link->data = mtp_m3ua_client_link_init(mtp3_link));
235 &
conf->sctp_dst_ipaddr,
conf->sctp_dst_port);
236 if (
conf->sctp_src_ipaddr.af != AF_UNSPEC) {
238 &
conf->sctp_src_ipaddr,
conf->sctp_src_port);
244 m3ua_client->link_index =
conf->m3ua_link_index;
245 m3ua_client->routing_context =
conf->m3ua_routing_context;
246 m3ua_client->ack_timeout =
conf->m3ua_ack_timeout;
247 m3ua_client->use_beat =
conf->m3ua_beat_interval;
252 if (
conf->m3ua_routes_is_set ||
conf->m3ua_routes.dpc_is_set) {
259 mtp3_link->reset(mtp3_link);
290 for (p =
buff; p < end; p++) {
293 slen = write(ofd->fd, p, end - p);
299 if (errno == EAGAIN) {
304 DEBUG3(
"Server core - Got EAGAIN (no buffer space left), waiting for pipe to become writable");
309 FD_SET(ofd->fd, &error_set);
310 FD_SET(ofd->fd, &write_set);
316 ret = select(ofd->fd + 1, NULL, &write_set, &error_set, NULL);
317 }
while ((ret == -1) && (errno == EINTR));
322 if ((ret > 0) && !FD_ISSET(ofd->fd, &error_set))
continue;
325 ERROR(
"Server core - Failed writing to pipe (%i): %s", ofd->fd,
fr_syserror(errno));
347 if (what & BSC_FD_EXCEPT) {
348 ERROR(
"pipe (%i) closed by osmocom thread, event thread exiting", ofd->fd);
353 if (!(what & BSC_FD_READ))
return 0;
355 len = read(ofd->fd, &ptr,
sizeof(ptr));
357 ERROR(
"osmocom thread - Failed reading from pipe (%i): %s", ofd->fd,
fr_syserror(errno));
361 DEBUG4(
"Ignoring zero length read");
364 if (len !=
sizeof(ptr)) {
365 ERROR(
"osmocom thread - Failed reading data from pipe (%i): Too short, "
366 "expected %zu bytes, got %zu bytes", ofd->fd,
sizeof(ptr), len);
371 DEBUG3(
"Event loop will exit");
379 DEBUG3(
"osmocom thread - Read %zu bytes from pipe %i (%p)", len, ofd->fd, ptr);
386 struct osmo_fd *req_ofd;
389 fd = *((
int *)txn->
request.data);
391 DEBUG3(
"osmocom thread - Registering req_pipe (%i)", fd);
403 DEBUG3(
"osmocom thread - Deregistering req_pipe (%i). Signalled by worker", ofd->fd);
411 DEBUG3(
"osmocom thread - Bringing link up");
420 DEBUG3(
"osmocom thread - Taking link down");
432 DEBUG3(
"osmocom thread - Processing map send auth info");
442 DEBUG3(
"osmocom thread - Event loop will exit");
481 if (socketpair(AF_UNIX, SOCK_STREAM, 0,
ctrl_pipe) < 0) {
482 ERROR(
"osmocom thread - Failed creating ctrl_pipe: %s",
fr_syserror(errno));
498 fd_set readset, writeset, exceptset;
505 high_fd = osmo_fd_fill_fds(&readset, &writeset, &exceptset);
506 if (high_fd == 0)
break;
508 DEBUG3(
"osmocom thread - Deferring exit, waiting for fd %i", high_fd);
517 DEBUG2(
"osmocom thread - Event loop exiting");
529 sigemptyset(&sigmask);
530 sigaddset(&sigmask, SIGCHLD);
535 ERROR(
"main thread - Failed initialising SCCP layer");
547 pthread_sigmask(SIG_BLOCK, &sigmask, NULL);
550 ERROR(
"main thread - Failed spawning thread for multiplexer event loop: %s",
fr_syserror(errno));
565 ERROR(
"main thread - libosmo thread died");
571 DEBUG2(
"main thread - libosmo thread responding");
589 ERROR(
"worker - Failed signalling osmocom thread to exit");
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
static sem_t event_thread_running
static pthread_t event_thread
static int event_link_up(TALLOC_CTX *ctx, sigtran_conn_t **out, sigtran_conn_conf_t *conf)
Bring up SCTP/M3UA/MTP3/SCCP.
static void * sigtran_event_loop(UNUSED void *instance)
Enter the libosmo event loop.
static int event_link_down(sigtran_conn_t *conn)
Take down a sigtran link.
static struct osmo_fd * ofd_create(TALLOC_CTX *ctx, int fd, osmo_cb_func func, void *data)
Register a new osmocom file descriptor callback.
int sigtran_event_submit(struct osmo_fd *ofd, sigtran_transaction_t *txn)
Send response.
int sigtran_event_start(void)
Start the libosmo event loop.
int sigtran_event_exit(void)
Signal that libosmo should exit.
int(* osmo_cb_func)(struct osmo_fd *fd, unsigned int what)
static int event_process_request(struct osmo_fd *ofd, unsigned int what)
Processes a request for a new pipe from a worker thread.
static int sigtran_m3ua_route_from_conf(UNUSED TALLOC_CTX *ctx, struct mtp_m3ua_client_link *client, sigtran_m3ua_route_t *conf)
Add a route to an m3ua_association.
static int _ofd_free(struct osmo_fd *ofd)
Unregister a osmocom_fd from the event loop, and close it.
static int _mtp3_link_free(struct mtp_link *mtp3_link)
Shutdown the MTP3 link gracefully if it's being freed.
void sigtran_log_init(TALLOC_CTX *ctx)
Patch our logging system into libosmo's.
void sigtran_sccp_incoming(UNUSED struct mtp_link_set *set, struct msgb *msg, UNUSED int sls)
Wrapper to pass data off to libsccp for processing.
void sigtran_sccp_global_free(void)
int sigtran_tcap_outgoing(UNUSED struct msgb *msg_in, void *ctx, sigtran_transaction_t *txn, UNUSED struct osmo_fd *ofd)
Send a request with static MAP data in it.
int sigtran_sscp_init(sigtran_conn_t *conn)
Initialise libscctp.
int sigtran_sccp_global_init(void)
int fr_schedule_pthread_create(pthread_t *thread, void *(*func)(void *), void *arg)
Creates a new thread using our standard set of options.
Signals that can be sent to a request.
Declarations for various sigtran functions.
@ SIGTRAN_REQUEST_THREAD_REGISTER
New worker thread to register.
@ SIGTRAN_REQUEST_MAP_SEND_AUTH_INFO
Request auth info.
@ SIGTRAN_REQUEST_LINK_DOWN
Take down a link.
@ SIGTRAN_REQUEST_THREAD_UNREGISTER
Worker thread to unregister.
@ SIGTRAN_REQUEST_EXIT
Causes the event loop to exit.
@ SIGTRAN_REQUEST_LINK_UP
Bring up a link.
@ SIGTRAN_RESPONSE_OK
Request succeeded.
@ SIGTRAN_RESPONSE_FAIL
Request failed.
struct mtp_link_set * mtp3_link_set
struct sigtran_transaction::@173 response
sigtran_conn_t const * conn
Connection to send request on.
sigtran_conn_conf_t * conf
struct sigtran_transaction::@172 request
struct sigtran_transaction::@174 ctx
struct mtp_link * mtp3_link
struct bsc_data * bsc_data
Represents a connection to a remote SS7 entity.
Configures a M3UA/MTP3/SCCP stack.
MAP send auth info request.
Request and response from the event loop.
static char buff[sizeof("18446744073709551615")+3]
int sigtran_client_do_transaction(int fd, sigtran_transaction_t *txn)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
static size_t char ** out