The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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
78int ctrl_pipe[2] = { -1, -1 }; /* Pipes are unidirectional */
79static pthread_t event_thread;
81static bool do_exit = false;
82
83typedef 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 */
90static 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 */
109static 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 */
130static 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 */
139static 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 */
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 */
283int 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 */
340static 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) {
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 */
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) {
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) {
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 */
470static 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:315
#define MEM(x)
Definition debug.h:36
#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
unsigned char uint8_t
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 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
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 int event_link_down(sigtran_conn_t *conn)
Take down a sigtran link.
Definition event.c:270
int sigtran_event_submit(struct osmo_fd *ofd, sigtran_transaction_t *txn)
Send response.
Definition event.c:283
static void * sigtran_event_loop(UNUSED void *instance)
Enter the libosmo event loop.
Definition event.c:470
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 fr_assert(_expr)
Definition rad_assert.h:38
#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
sigtran_conn_t const * conn
Connection to send request on.
Definition sigtran.h:192
sigtran_conn_conf_t * conf
Definition sigtran.h:181
struct mtp_link * mtp3_link
Definition sigtran.h:185
struct sigtran_transaction::@176 ctx
struct sigtran_transaction::@175 response
struct bsc_data * bsc_data
Definition sigtran.h:183
struct sigtran_transaction::@174 request
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
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