The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
event.c
Go to the documentation of this file.
1 /*
2  * @copyright (c) 2016, Network RADIUS SAS (license@networkradius.com)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of Network RADIUS SAS nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * $Id: 6278db1a8aa116790bf03a75bdd213862a640cfb $
30  * @file rlm_sigtran/event.c
31  * @brief separate eventing thread to run libosmocore's event loop
32  *
33  * libosmocore is not thread safe, none of the event loop access functions
34  * support synchronised access by multiple threads.
35  *
36  * Writing a shim layer and overloading the libosmo functions would work
37  * but is likely to be fragile.
38  *
39  * Instead, we run a special thread to handle all requests to SS7 entities.
40  *
41  * This thread runs the libosmocore event loop, and select()s over the SCTP
42  * FDs libosmo* creates, and a pipe we create (to allow communication
43  * with worker threads).
44  *
45  * You might except performance using this model to be terrible. But the
46  * fact that libosmo is entirely async, and there's no heavy crypto being
47  * performed, I suspect that this thread is unlikely to become a bottleneck.
48  *
49  * In future when we have our own async event loop, we can look at submitting
50  * patches to libosmocore to allow integration with external event loops.
51  *
52  * @note We rely on the fact that writes to a pipe of less than PIPE_BUF, are
53  * atomic and not interleaved.
54  *
55  * @author Arran Cudbard-Bell
56  *
57  * @copyright 2016 Network RADIUS SAS (license@networkradius.com)
58  */
59 #define LOG_PREFIX "sigtran"
60 
61 #include <osmocom/core/talloc.h>
62 
63 #include <freeradius-devel/server/base.h>
64 #include <freeradius-devel/util/debug.h>
65 #include <freeradius-devel/io/schedule.h>
66 #include <unistd.h>
67 #include <semaphore.h>
68 #include <signal.h>
69 
70 #include <osmocom/core/logging.h>
71 #include <osmocom/sccp/sccp_types.h>
72 #include <osmocom/mtp/mtp_level3.h>
73 
74 #include "libosmo-m3ua/include/bsc_data.h"
75 #include "libosmo-m3ua/include/sctp_m3ua.h"
76 #include "sigtran.h"
77 
78 int ctrl_pipe[2] = { -1, -1 }; /* Pipes are unidirectional */
79 static pthread_t event_thread;
80 static sem_t event_thread_running;
81 static bool do_exit = false;
82 
83 typedef int (*osmo_cb_func)(struct osmo_fd *fd, unsigned int what);
84 
85 /** Unregister a osmocom_fd from the event loop, and close it
86  *
87  * @param ofd to unregister.
88  * @return 0.
89  */
90 static int _ofd_free(struct osmo_fd *ofd)
91 {
92  osmo_fd_unregister(ofd);
93  close(ofd->fd);
94  return 0;
95 }
96 
97 /** Register a new osmocom file descriptor callback
98  *
99  * @param ctx to allocate osmocom_fd in.
100  * @param fd to associate with osmocom_fd .
101  * @param func to call when fd becomes readable.
102  * @param data private contextual data.
103  * @return
104  * - NULL on error.
105  * - New osmocom_fd on success.
106  * Freeing unregisters osmocom_fd from event loop,
107  * and closes file descriptor.
108  */
109 static struct osmo_fd *ofd_create(TALLOC_CTX *ctx, int fd, osmo_cb_func func, void *data)
110 {
111  struct osmo_fd *ofd;
112 
113  MEM(ofd = talloc_zero(ctx, struct osmo_fd));
114  ofd->fd = fd;
115  ofd->when = BSC_FD_READ;
116  ofd->cb = func;
117  ofd->data = data;
118  if (osmo_fd_register(ofd) < 0) {
119  ERROR("Failed registering pipe %i", fd);
120  return NULL;
121  }
122  talloc_set_destructor(ofd, _ofd_free);
123 
124  return ofd;
125 }
126 
127 /** Shutdown the MTP3 link gracefully if it's being freed
128  *
129  */
130 static int _mtp3_link_free(struct mtp_link *mtp3_link)
131 {
132  mtp3_link->shutdown(mtp3_link);
133  return 0;
134 }
135 
136 /** Add a route to an m3ua_association
137  *
138  */
139 static int sigtran_m3ua_route_from_conf(UNUSED TALLOC_CTX *ctx,
140  struct mtp_m3ua_client_link *client,
142 {
143  struct mtp_m3ua_reg_req *route;
144 
145  size_t i;
146 
147  route = mtp_m3ua_reg_req_add(client);
148  if (!route) return -1;
149 
150  route->dpc = conf->dpc;
151 
152  if (conf->opc) {
153  struct mtp_m3ua_opc *opc;
154 
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);
159  }
160  }
161 
162  if (conf->si) {
163  struct mtp_m3ua_si *si;
164 
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);
169  }
170  }
171 
172  return 0;
173 }
174 
175 /** Bring up SCTP/M3UA/MTP3/SCCP
176  *
177  * @note The final version needs to be much more complex. We can only have one
178  * event loop per instance of rlm_sigtran, so we need to record link references
179  * and reuse existing SCTP/MTP3 connections where appropriate.
180  *
181  * @param[in] ctx to allocate connection data in.
182  * @param[out] out where to write the new sigtran connection.
183  * @param[in] conf for the connection. Specifies SCTP/M3UA/MTP3/SCCP parameters.
184  * @return
185  * - 0 on success.
186  * - -1 on failure.
187  */
188 static int event_link_up(TALLOC_CTX *ctx, sigtran_conn_t **out, sigtran_conn_conf_t *conf)
189 {
190  struct mtp_link_set *mtp3_link_set;
191  struct mtp_link *mtp3_link;
192  struct mtp_m3ua_client_link *m3ua_client;
193  socklen_t salen;
194 
195  sigtran_conn_t *conn;
196 
197  conn = talloc_zero(ctx, sigtran_conn_t);
198  conn->conf = conf;
199 
200  /* Temporarily disable until we can fix the osmocom select loop */
201 #if 0
202  conn->bsc_data = bsc_data_alloc(conn);
203  talloc_set_destructor(conn, _conn_free);
204 #else
205  conn->bsc_data = bsc_data_alloc(ctx);
206 #endif
207  /*
208  * Create a new link. This will run over SCTP/M3UA
209  */
210  MEM(mtp3_link_set = conn->mtp3_link_set = mtp_link_set_alloc(conn->bsc_data));
211 
212  mtp3_link_set->dpc = conf->mtp3_dpc; /* Next hop Point Code */
213  mtp3_link_set->opc = conf->mtp3_opc;
214 
215  /*
216  * Patch in our SCCP receive function
217  */
218  sigtran_sscp_init(conn);
219  mtp_link_set_sccp_data_available_cb(mtp3_link_set, sigtran_sccp_incoming);
220 
221  MEM(mtp3_link = conn->mtp3_link = mtp_link_alloc(mtp3_link_set));
222  talloc_set_destructor(mtp3_link, _mtp3_link_free);
223  mtp3_link->name = talloc_strdup(mtp3_link, "default");
224  mtp3_link->nr = 1;
225 
226  /*
227  * Sets up the transport for the MTP3 link
228  */
229  MEM(m3ua_client = mtp3_link->data = mtp_m3ua_client_link_init(mtp3_link));
230 
231  /*
232  * Setup SCTP src/dst address
233  */
234  fr_ipaddr_to_sockaddr(&m3ua_client->remote, &salen,
235  &conf->sctp_dst_ipaddr, conf->sctp_dst_port);
236  if (conf->sctp_src_ipaddr.af != AF_UNSPEC) {
237  fr_ipaddr_to_sockaddr(&m3ua_client->local, &salen,
238  &conf->sctp_src_ipaddr, conf->sctp_src_port);
239  }
240 
241  /*
242  * Setup M3UA link parameters
243  */
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;
248 
249  /*
250  * Add the route.
251  */
252  if (conf->m3ua_routes_is_set || conf->m3ua_routes.dpc_is_set) {
253  if (sigtran_m3ua_route_from_conf(m3ua_client, m3ua_client, &conf->m3ua_routes) < 0) return -1;
254  }
255 
256  /*
257  * Bring up the MTP3 link
258  */
259  mtp3_link->reset(mtp3_link);
260 
261  *out = conn;
262 
263  return 0;
264 }
265 
266 /** Take down a sigtran link
267  *
268  * @note Probably need to do more than just freeing the memory
269  */
271 {
272  talloc_free(conn);
273  return 0;
274 }
275 
276 /** Send response
277  *
278  * @note Works for both blocking and non-blocking sockets
279  *
280  * @param[in] ofd to write response notification to.
281  * @param[in] txn we're confirming.
282  */
283 int sigtran_event_submit(struct osmo_fd *ofd, sigtran_transaction_t *txn)
284 {
285  uint8_t buff[sizeof(void *)];
286  uint8_t *p = buff, *end = buff + sizeof(buff);
287 
288  memcpy(buff, &txn, sizeof(buff));
289 
290  for (p = buff; p < end; p++) {
291  ssize_t slen;
292 
293  slen = write(ofd->fd, p, end - p);
294  if (slen > 0) {
295  p += slen;
296  continue;
297  }
298 
299  if (errno == EAGAIN) {
300  int ret;
301  fd_set error_set;
302  fd_set write_set;
303 
304  DEBUG3("Server core - Got EAGAIN (no buffer space left), waiting for pipe to become writable");
305 
306  FD_ZERO(&error_set);
307  FD_ZERO(&write_set);
308 
309  FD_SET(ofd->fd, &error_set);
310  FD_SET(ofd->fd, &write_set);
311 
312  /*
313  * Don't let signals mess up the select
314  */
315  do {
316  ret = select(ofd->fd + 1, NULL, &write_set, &error_set, NULL);
317  } while ((ret == -1) && (errno == EINTR));
318 
319  /*
320  * If there wasn't an error try again...
321  */
322  if ((ret > 0) && !FD_ISSET(ofd->fd, &error_set)) continue;
323  }
324 
325  ERROR("Server core - Failed writing to pipe (%i): %s", ofd->fd, fr_syserror(errno));
326  return -1;
327  }
328 
329  return 0;
330 }
331 
332 /** Processes a request for a new pipe from a worker thread
333  *
334  * @param ofd for the main ctrl_pipe.
335  * @param what happened.
336  * @return
337  * - 0 on success, with pointer written to registration pipe for new osmo_fd.
338  * - -1 on error, with NULL pointer written to registration pipe.
339  */
340 static int event_process_request(struct osmo_fd *ofd, unsigned int what)
341 {
343 
344  void *ptr;
345  ssize_t len;
346 
347  if (what & BSC_FD_EXCEPT) {
348  ERROR("pipe (%i) closed by osmocom thread, event thread exiting", ofd->fd);
349  do_exit = true;
350  return -1;
351  }
352 
353  if (!(what & BSC_FD_READ)) return 0;
354 
355  len = read(ofd->fd, &ptr, sizeof(ptr));
356  if (len < 0) {
357  ERROR("osmocom thread - Failed reading from pipe (%i): %s", ofd->fd, fr_syserror(errno));
358  return -1;
359  }
360  if (len == 0) {
361  DEBUG4("Ignoring zero length read");
362  return 0;
363  }
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);
367  ptr = NULL;
368 
369  if (sigtran_event_submit(ofd, NULL) < 0) {
370  fatal_error:
371  DEBUG3("Event loop will exit");
372  do_exit = true;
373  return -1;
374  }
375 
376  return -1;
377  }
378 
379  DEBUG3("osmocom thread - Read %zu bytes from pipe %i (%p)", len, ofd->fd, ptr);
380 
381  txn = talloc_get_type_abort(ptr, sigtran_transaction_t);
382  txn->ctx.ofd = ofd;
383  switch (txn->request.type) {
385  {
386  struct osmo_fd *req_ofd;
387  int fd;
388 
389  fd = *((int *)txn->request.data); /* Not talloced */
390 
391  DEBUG3("osmocom thread - Registering req_pipe (%i)", fd);
392 
393  req_ofd = ofd_create(ofd->data, fd, event_process_request, NULL);
394  if (!req_ofd) {
395  txn->response.type = SIGTRAN_RESPONSE_FAIL;
396  } else {
397  txn->response.type = SIGTRAN_RESPONSE_OK;
398  }
399  }
400  break;
401 
403  DEBUG3("osmocom thread - Deregistering req_pipe (%i). Signalled by worker", ofd->fd);
404  txn->response.type = SIGTRAN_RESPONSE_OK;
405 
406  if (sigtran_event_submit(ofd, txn) < 0) goto fatal_error;
407  talloc_free(ofd); /* Ordering is important */
408  return 0;
409 
411  DEBUG3("osmocom thread - Bringing link up");
412  if (event_link_up(ofd->data, (sigtran_conn_t **)&txn->response.data, txn->request.data) < 0) { /* Struct not talloced */
413  txn->response.type = SIGTRAN_RESPONSE_FAIL;
414  } else {
415  txn->response.type = SIGTRAN_RESPONSE_OK;
416  }
417  break;
418 
420  DEBUG3("osmocom thread - Taking link down");
421  if (event_link_down(talloc_get_type_abort(txn->request.data, sigtran_conn_t)) < 0) {
422  txn->response.type = SIGTRAN_RESPONSE_FAIL;
423  } else {
424  txn->response.type = SIGTRAN_RESPONSE_OK;
425  }
426  break;
427 
429  {
430  sigtran_map_send_auth_info_req_t *req = talloc_get_type_abort(txn->request.data,
432  DEBUG3("osmocom thread - Processing map send auth info");
433  if (sigtran_tcap_outgoing(NULL, req->conn, txn, ofd) < 0) {
434  txn->response.type = SIGTRAN_RESPONSE_FAIL;
435  } else {
436  return 0; /* Keep caller blocked until we get a response */
437  }
438  }
439  break;
440 
442  DEBUG3("osmocom thread - Event loop will exit");
443  do_exit = true;
444  txn->response.type = SIGTRAN_RESPONSE_OK;
445 
446  if (sigtran_event_submit(ofd, txn) < 0) goto fatal_error;
447  talloc_free(ofd); /* Ordering is important */
448  return 0;
449 
450 #ifndef NDEBUG
452  txn->response.type = SIGTRAN_RESPONSE_OK;
453  break;
454 #endif
455 
456  default:
457  fr_assert(0);
458  goto fatal_error;
459  }
460 
461  if (sigtran_event_submit(ofd, txn) < 0) goto fatal_error;
462 
463  return 0;
464 }
465 
466 /** Enter the libosmo event loop
467  *
468  * Will run until the thread is killed, or signalled to exit on the ctrl_pipe.
469  */
470 static void *sigtran_event_loop(UNUSED void *instance)
471 {
472  TALLOC_CTX *ctx = talloc_init_const("sigtran_event_ctx");
473 
474  fr_assert((ctrl_pipe[0] < 0) && (ctrl_pipe[1] < 0)); /* Ensure only one instance exists */
475 
476  /*
477  * Patch in libosmo's logging system to ours
478  */
479  sigtran_log_init(ctx);
480 
481  if (socketpair(AF_UNIX, SOCK_STREAM, 0, ctrl_pipe) < 0) {
482  ERROR("osmocom thread - Failed creating ctrl_pipe: %s", fr_syserror(errno));
483  return NULL;
484  }
485  if (!ofd_create(ctx, ctrl_pipe[1], event_process_request, ctx)) return NULL;
486 
487  DEBUG2("osmocom thread - Entering event loop, listening on fd %i (client fd %i)", ctrl_pipe[1], ctrl_pipe[0]);
488 
489  sem_post(&event_thread_running); /* Up enough to be ok! */
490 
491  /*
492  * The main event loop.
493  */
494  while (true) {
495  osmo_select_main(0);
496  if (do_exit) {
497 #if 0
498  fd_set readset, writeset, exceptset;
499  int high_fd;
500 
501  FD_ZERO(&readset);
502  FD_ZERO(&writeset);
503  FD_ZERO(&exceptset);
504 
505  high_fd = osmo_fd_fill_fds(&readset, &writeset, &exceptset);
506  if (high_fd == 0) break;
507 
508  DEBUG3("osmocom thread - Deferring exit, waiting for fd %i", high_fd);
509 #else
510  break;
511 #endif
512  }
513  }
514 
515  talloc_free(ctx); /* Also frees ctrl pipe ofd (which closes ctrl_pipe[1]) */
516 
517  DEBUG2("osmocom thread - Event loop exiting");
518 
519  return NULL;
520 }
521 
522 /** Start the libosmo event loop
523  *
524  */
526 {
527  sigset_t sigmask;
528 
529  sigemptyset(&sigmask);
530  sigaddset(&sigmask, SIGCHLD);
531 
532  sem_init(&event_thread_running, 0, 0);
533 
534  if (sigtran_sccp_global_init() < 0) {
535  ERROR("main thread - Failed initialising SCCP layer");
536  return -1;
537  }
538 
539  /*
540  * Reset the signal mask some of the
541  * osmocom code seems to mess with it.
542  *
543  * This is so that old Linux kernels
544  * and libkqueue posix/proc work
545  * correctly.
546  */
547  pthread_sigmask(SIG_BLOCK, &sigmask, NULL);
548 
550  ERROR("main thread - Failed spawning thread for multiplexer event loop: %s", fr_syserror(errno));
551  return -1;
552  }
553 
554  sem_wait(&event_thread_running);
555 
556 #ifndef NDEBUG
557  {
559 
560  txn = talloc_zero(NULL, sigtran_transaction_t);
561  txn->request.type = SIGTRAN_REQUEST_TEST;
562 
563  if ((sigtran_client_do_transaction(ctrl_pipe[0], txn) < 0) ||
564  (txn->response.type != SIGTRAN_RESPONSE_OK)) {
565  ERROR("main thread - libosmo thread died");
566  talloc_free(txn);
567  return -1;
568  }
569  talloc_free(txn);
570 
571  DEBUG2("main thread - libosmo thread responding");
572  }
573 #endif
574 
575  return 0;
576 }
577 
578 /** Signal that libosmo should exit
579  *
580  */
582 {
584 
585  txn = talloc_zero(NULL, sigtran_transaction_t);
586  txn->request.type = SIGTRAN_REQUEST_EXIT;
587 
588  if ((sigtran_client_do_transaction(ctrl_pipe[0], txn) < 0) || (txn->response.type != SIGTRAN_RESPONSE_OK)) {
589  ERROR("worker - Failed signalling osmocom thread to exit");
590  talloc_free(txn);
591  return -1;
592  }
593  talloc_free(txn);
594 
595  close(ctrl_pipe[0]);
596  ctrl_pipe[0] = -1;
597  ctrl_pipe[1] = -1;
598 
599  pthread_join(event_thread, NULL);
600 
602 
603  return 0;
604 }
#define UNUSED
Definition: build.h:313
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
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.
Definition: inet.c:1392
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define DEBUG4(_fmt,...)
Definition: log.h:267
talloc_free(reap)
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
int ctrl_pipe[2]
Definition: event.c:78
static sem_t event_thread_running
Definition: event.c:80
static bool do_exit
Definition: event.c:81
static pthread_t event_thread
Definition: event.c:79
static int event_link_up(TALLOC_CTX *ctx, sigtran_conn_t **out, sigtran_conn_conf_t *conf)
Bring up SCTP/M3UA/MTP3/SCCP.
Definition: event.c:188
static void * sigtran_event_loop(UNUSED void *instance)
Enter the libosmo event loop.
Definition: event.c:470
static int event_link_down(sigtran_conn_t *conn)
Take down a sigtran link.
Definition: event.c:270
static struct osmo_fd * ofd_create(TALLOC_CTX *ctx, int fd, osmo_cb_func func, void *data)
Register a new osmocom file descriptor callback.
Definition: event.c:109
int sigtran_event_submit(struct osmo_fd *ofd, sigtran_transaction_t *txn)
Send response.
Definition: event.c:283
int sigtran_event_start(void)
Start the libosmo event loop.
Definition: event.c:525
int sigtran_event_exit(void)
Signal that libosmo should exit.
Definition: event.c:581
int(* osmo_cb_func)(struct osmo_fd *fd, unsigned int what)
Definition: event.c:83
static int event_process_request(struct osmo_fd *ofd, unsigned int what)
Processes a request for a new pipe from a worker thread.
Definition: event.c:340
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.
Definition: event.c:139
static int _ofd_free(struct osmo_fd *ofd)
Unregister a osmocom_fd from the event loop, and close it.
Definition: event.c:90
static int _mtp3_link_free(struct mtp_link *mtp3_link)
Shutdown the MTP3 link gracefully if it's being freed.
Definition: event.c:130
void sigtran_log_init(TALLOC_CTX *ctx)
Patch our logging system into libosmo's.
Definition: log.c:62
#define DEBUG2(fmt,...)
Definition: radclient.h:43
static rs_t * conf
Definition: radsniff.c:53
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.
Definition: sccp.c:352
void sigtran_sccp_global_free(void)
Definition: sccp.c:385
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.
Definition: sccp.c:98
int sigtran_sscp_init(sigtran_conn_t *conn)
Initialise libscctp.
Definition: sccp.c:360
int sigtran_sccp_global_init(void)
Definition: sccp.c:371
int fr_schedule_pthread_create(pthread_t *thread, void *(*func)(void *), void *arg)
Creates a new thread using our standard set of options.
Definition: schedule.c:425
Signals that can be sent to a request.
Declarations for various sigtran functions.
@ SIGTRAN_REQUEST_THREAD_REGISTER
New worker thread to register.
Definition: sigtran.h:43
@ SIGTRAN_REQUEST_MAP_SEND_AUTH_INFO
Request auth info.
Definition: sigtran.h:47
@ SIGTRAN_REQUEST_LINK_DOWN
Take down a link.
Definition: sigtran.h:46
@ SIGTRAN_REQUEST_THREAD_UNREGISTER
Worker thread to unregister.
Definition: sigtran.h:44
@ SIGTRAN_REQUEST_EXIT
Causes the event loop to exit.
Definition: sigtran.h:48
@ SIGTRAN_REQUEST_TEST
Definition: sigtran.h:50
@ SIGTRAN_REQUEST_LINK_UP
Bring up a link.
Definition: sigtran.h:45
@ SIGTRAN_RESPONSE_OK
Request succeeded.
Definition: sigtran.h:55
@ SIGTRAN_RESPONSE_FAIL
Request failed.
Definition: sigtran.h:58
struct mtp_link_set * mtp3_link_set
Definition: sigtran.h:184
struct sigtran_transaction::@173 response
sigtran_conn_t const * conn
Connection to send request on.
Definition: sigtran.h:192
sigtran_conn_conf_t * conf
Definition: sigtran.h:181
struct sigtran_transaction::@172 request
struct sigtran_transaction::@174 ctx
struct mtp_link * mtp3_link
Definition: sigtran.h:185
struct bsc_data * bsc_data
Definition: sigtran.h:183
Represents a connection to a remote SS7 entity.
Definition: sigtran.h:180
Configures a M3UA/MTP3/SCCP stack.
Definition: sigtran.h:143
MAP send auth info request.
Definition: sigtran.h:191
Request and response from the event loop.
Definition: sigtran.h:75
static char buff[sizeof("18446744073709551615")+3]
Definition: size_tests.c:41
int sigtran_client_do_transaction(int fd, sigtran_transaction_t *txn)
Definition: client.c:45
fr_assert(0)
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.
Definition: syserror.c:243
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition: talloc.h:112
close(uq->fd)
static fr_slen_t data
Definition: value.h:1265
static size_t char ** out
Definition: value.h:997