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>
68#include <osmocom/core/logging.h>
69#include <osmocom/sccp/sccp_types.h>
70#include <osmocom/mtp/mtp_level3.h>
72#include "libosmo-m3ua/include/bsc_data.h"
73#include "libosmo-m3ua/include/sctp_m3ua.h"
90 osmo_fd_unregister(ofd);
111 MEM(ofd = talloc_zero(ctx,
struct osmo_fd));
113 ofd->when = BSC_FD_READ;
116 if (osmo_fd_register(ofd) < 0) {
117 ERROR(
"Failed registering pipe %i", fd);
130 mtp3_link->shutdown(mtp3_link);
138 struct mtp_m3ua_client_link *client,
141 struct mtp_m3ua_reg_req *route;
145 route = mtp_m3ua_reg_req_add(client);
146 if (!route)
return -1;
148 route->dpc =
conf->dpc;
151 struct mtp_m3ua_opc *opc;
153 for (i = 0; i < talloc_array_length(
conf->opc); i++) {
154 opc = talloc_zero(route,
struct mtp_m3ua_opc);
155 opc->opc =
conf->opc[i];
156 llist_add_tail(&opc->list, &route->opc);
161 struct mtp_m3ua_si *si;
163 for (i = 0; i < talloc_array_length(
conf->si); i++) {
164 si = talloc_zero(route,
struct mtp_m3ua_si);
165 si->si =
conf->si[i];
166 llist_add_tail(&si->list, &route->si);
188 struct mtp_link_set *mtp3_link_set;
189 struct mtp_link *mtp3_link;
190 struct mtp_m3ua_client_link *m3ua_client;
200 conn->
bsc_data = bsc_data_alloc(conn);
201 talloc_set_destructor(conn, _conn_free);
203 conn->
bsc_data = bsc_data_alloc(ctx);
210 mtp3_link_set->dpc =
conf->mtp3_dpc;
211 mtp3_link_set->opc =
conf->mtp3_opc;
219 MEM(mtp3_link = conn->
mtp3_link = mtp_link_alloc(mtp3_link_set));
227 MEM(m3ua_client = mtp3_link->data = mtp_m3ua_client_link_init(mtp3_link));
233 &
conf->sctp_dst_ipaddr,
conf->sctp_dst_port);
234 if (
conf->sctp_src_ipaddr.af != AF_UNSPEC) {
236 &
conf->sctp_src_ipaddr,
conf->sctp_src_port);
242 m3ua_client->link_index =
conf->m3ua_link_index;
243 m3ua_client->routing_context =
conf->m3ua_routing_context;
244 m3ua_client->ack_timeout =
conf->m3ua_ack_timeout;
245 m3ua_client->use_beat =
conf->m3ua_beat_interval;
250 if (
conf->m3ua_routes_is_set ||
conf->m3ua_routes.dpc_is_set) {
257 mtp3_link->reset(mtp3_link);
288 for (p =
buff; p < end; p++) {
291 slen = write(ofd->fd, p, end - p);
297 if (errno == EAGAIN) {
302 DEBUG3(
"Server core - Got EAGAIN (no buffer space left), waiting for pipe to become writable");
307 FD_SET(ofd->fd, &error_set);
308 FD_SET(ofd->fd, &write_set);
314 ret = select(ofd->fd + 1, NULL, &write_set, &error_set, NULL);
315 }
while ((ret == -1) && (errno == EINTR));
320 if ((ret > 0) && !FD_ISSET(ofd->fd, &error_set))
continue;
323 ERROR(
"Server core - Failed writing to pipe (%i): %s", ofd->fd,
fr_syserror(errno));
345 if (what & BSC_FD_EXCEPT) {
346 ERROR(
"pipe (%i) closed by osmocom thread, event thread exiting", ofd->fd);
351 if (!(what & BSC_FD_READ))
return 0;
353 len = read(ofd->fd, &ptr,
sizeof(ptr));
355 ERROR(
"osmocom thread - Failed reading from pipe (%i): %s", ofd->fd,
fr_syserror(errno));
359 DEBUG4(
"Ignoring zero length read");
362 if (len !=
sizeof(ptr)) {
363 ERROR(
"osmocom thread - Failed reading data from pipe (%i): Too short, "
364 "expected %zu bytes, got %zu bytes", ofd->fd,
sizeof(ptr), len);
369 DEBUG3(
"Event loop will exit");
377 DEBUG3(
"osmocom thread - Read %zu bytes from pipe %i (%p)", len, ofd->fd, ptr);
384 struct osmo_fd *req_ofd;
387 fd = *((
int *)txn->
request.data);
389 DEBUG3(
"osmocom thread - Registering req_pipe (%i)", fd);
401 DEBUG3(
"osmocom thread - Deregistering req_pipe (%i). Signalled by worker", ofd->fd);
409 DEBUG3(
"osmocom thread - Bringing link up");
418 DEBUG3(
"osmocom thread - Taking link down");
430 DEBUG3(
"osmocom thread - Processing map send auth info");
440 DEBUG3(
"osmocom thread - Event loop will exit");
479 if (socketpair(AF_UNIX, SOCK_STREAM, 0,
ctrl_pipe) < 0) {
480 ERROR(
"osmocom thread - Failed creating ctrl_pipe: %s",
fr_syserror(errno));
496 fd_set readset, writeset, exceptset;
503 high_fd = osmo_fd_fill_fds(&readset, &writeset, &exceptset);
504 if (high_fd == 0)
break;
506 DEBUG3(
"osmocom thread - Deferring exit, waiting for fd %i", high_fd);
515 DEBUG2(
"osmocom thread - Event loop exiting");
527 sigemptyset(&sigmask);
528 sigaddset(&sigmask, SIGCHLD);
533 ERROR(
"main thread - Failed initialising SCCP layer");
545 pthread_sigmask(SIG_BLOCK, &sigmask, NULL);
548 ERROR(
"main thread - Failed spawning thread for multiplexer event loop: %s",
fr_syserror(errno));
563 ERROR(
"main thread - libosmo thread died");
569 DEBUG2(
"main thread - libosmo thread responding");
587 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 struct osmo_fd * ofd_create(TALLOC_CTX *ctx, int fd, osmo_cb_func func, void *data)
Register a new osmocom file descriptor callback.
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 int event_link_down(sigtran_conn_t *conn)
Take down a sigtran link.
int sigtran_event_submit(struct osmo_fd *ofd, sigtran_transaction_t *txn)
Send response.
static void * sigtran_event_loop(UNUSED void *instance)
Enter the libosmo event loop.
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::@191 request
sigtran_conn_t const * conn
Connection to send request on.
sigtran_conn_conf_t * conf
struct sigtran_transaction::@192 response
struct mtp_link * mtp3_link
struct sigtran_transaction::@193 ctx
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)
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.
#define talloc_strdup(_ctx, _str)
static size_t char ** out