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: 6105147fd89ad1bac18fb7d9d53afc461f9b1a10 $
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 <semaphore.h>
66#include <signal.h>
67
68#include <osmocom/core/logging.h>
69#include <osmocom/sccp/sccp_types.h>
70#include <osmocom/mtp/mtp_level3.h>
71
72#include "libosmo-m3ua/include/bsc_data.h"
73#include "libosmo-m3ua/include/sctp_m3ua.h"
74#include "sigtran.h"
75
76int ctrl_pipe[2] = { -1, -1 }; /* Pipes are unidirectional */
77static pthread_t event_thread;
79static bool do_exit = false;
80
81typedef int (*osmo_cb_func)(struct osmo_fd *fd, unsigned int what);
82
83/** Unregister a osmocom_fd from the event loop, and close it
84 *
85 * @param ofd to unregister.
86 * @return 0.
87 */
88static int _ofd_free(struct osmo_fd *ofd)
89{
90 osmo_fd_unregister(ofd);
91 close(ofd->fd);
92 return 0;
93}
94
95/** Register a new osmocom file descriptor callback
96 *
97 * @param ctx to allocate osmocom_fd in.
98 * @param fd to associate with osmocom_fd .
99 * @param func to call when fd becomes readable.
100 * @param data private contextual data.
101 * @return
102 * - NULL on error.
103 * - New osmocom_fd on success.
104 * Freeing unregisters osmocom_fd from event loop,
105 * and closes file descriptor.
106 */
107static struct osmo_fd *ofd_create(TALLOC_CTX *ctx, int fd, osmo_cb_func func, void *data)
108{
109 struct osmo_fd *ofd;
110
111 MEM(ofd = talloc_zero(ctx, struct osmo_fd));
112 ofd->fd = fd;
113 ofd->when = BSC_FD_READ;
114 ofd->cb = func;
115 ofd->data = data;
116 if (osmo_fd_register(ofd) < 0) {
117 ERROR("Failed registering pipe %i", fd);
118 return NULL;
119 }
120 talloc_set_destructor(ofd, _ofd_free);
121
122 return ofd;
123}
124
125/** Shutdown the MTP3 link gracefully if it's being freed
126 *
127 */
128static int _mtp3_link_free(struct mtp_link *mtp3_link)
129{
130 mtp3_link->shutdown(mtp3_link);
131 return 0;
132}
133
134/** Add a route to an m3ua_association
135 *
136 */
137static int sigtran_m3ua_route_from_conf(UNUSED TALLOC_CTX *ctx,
138 struct mtp_m3ua_client_link *client,
140{
141 struct mtp_m3ua_reg_req *route;
142
143 size_t i;
144
145 route = mtp_m3ua_reg_req_add(client);
146 if (!route) return -1;
147
148 route->dpc = conf->dpc;
149
150 if (conf->opc) {
151 struct mtp_m3ua_opc *opc;
152
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);
157 }
158 }
159
160 if (conf->si) {
161 struct mtp_m3ua_si *si;
162
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);
167 }
168 }
169
170 return 0;
171}
172
173/** Bring up SCTP/M3UA/MTP3/SCCP
174 *
175 * @note The final version needs to be much more complex. We can only have one
176 * event loop per instance of rlm_sigtran, so we need to record link references
177 * and reuse existing SCTP/MTP3 connections where appropriate.
178 *
179 * @param[in] ctx to allocate connection data in.
180 * @param[out] out where to write the new sigtran connection.
181 * @param[in] conf for the connection. Specifies SCTP/M3UA/MTP3/SCCP parameters.
182 * @return
183 * - 0 on success.
184 * - -1 on failure.
185 */
187{
188 struct mtp_link_set *mtp3_link_set;
189 struct mtp_link *mtp3_link;
190 struct mtp_m3ua_client_link *m3ua_client;
191 socklen_t salen;
192
193 sigtran_conn_t *conn;
194
195 conn = talloc_zero(ctx, sigtran_conn_t);
196 conn->conf = conf;
197
198 /* Temporarily disable until we can fix the osmocom select loop */
199#if 0
200 conn->bsc_data = bsc_data_alloc(conn);
201 talloc_set_destructor(conn, _conn_free);
202#else
203 conn->bsc_data = bsc_data_alloc(ctx);
204#endif
205 /*
206 * Create a new link. This will run over SCTP/M3UA
207 */
208 MEM(mtp3_link_set = conn->mtp3_link_set = mtp_link_set_alloc(conn->bsc_data));
209
210 mtp3_link_set->dpc = conf->mtp3_dpc; /* Next hop Point Code */
211 mtp3_link_set->opc = conf->mtp3_opc;
212
213 /*
214 * Patch in our SCCP receive function
215 */
216 sigtran_sscp_init(conn);
217 mtp_link_set_sccp_data_available_cb(mtp3_link_set, sigtran_sccp_incoming);
218
219 MEM(mtp3_link = conn->mtp3_link = mtp_link_alloc(mtp3_link_set));
220 talloc_set_destructor(mtp3_link, _mtp3_link_free);
221 mtp3_link->name = talloc_strdup(mtp3_link, "default");
222 mtp3_link->nr = 1;
223
224 /*
225 * Sets up the transport for the MTP3 link
226 */
227 MEM(m3ua_client = mtp3_link->data = mtp_m3ua_client_link_init(mtp3_link));
228
229 /*
230 * Setup SCTP src/dst address
231 */
232 fr_ipaddr_to_sockaddr(&m3ua_client->remote, &salen,
233 &conf->sctp_dst_ipaddr, conf->sctp_dst_port);
234 if (conf->sctp_src_ipaddr.af != AF_UNSPEC) {
235 fr_ipaddr_to_sockaddr(&m3ua_client->local, &salen,
236 &conf->sctp_src_ipaddr, conf->sctp_src_port);
237 }
238
239 /*
240 * Setup M3UA link parameters
241 */
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;
246
247 /*
248 * Add the route.
249 */
250 if (conf->m3ua_routes_is_set || conf->m3ua_routes.dpc_is_set) {
251 if (sigtran_m3ua_route_from_conf(m3ua_client, m3ua_client, &conf->m3ua_routes) < 0) return -1;
252 }
253
254 /*
255 * Bring up the MTP3 link
256 */
257 mtp3_link->reset(mtp3_link);
258
259 *out = conn;
260
261 return 0;
262}
263
264/** Take down a sigtran link
265 *
266 * @note Probably need to do more than just freeing the memory
267 */
269{
270 talloc_free(conn);
271 return 0;
272}
273
274/** Send response
275 *
276 * @note Works for both blocking and non-blocking sockets
277 *
278 * @param[in] ofd to write response notification to.
279 * @param[in] txn we're confirming.
280 */
281int sigtran_event_submit(struct osmo_fd *ofd, sigtran_transaction_t *txn)
282{
283 uint8_t buff[sizeof(void *)];
284 uint8_t *p = buff, *end = buff + sizeof(buff);
285
286 memcpy(buff, &txn, sizeof(buff));
287
288 for (p = buff; p < end; p++) {
289 ssize_t slen;
290
291 slen = write(ofd->fd, p, end - p);
292 if (slen > 0) {
293 p += slen;
294 continue;
295 }
296
297 if (errno == EAGAIN) {
298 int ret;
299 fd_set error_set;
300 fd_set write_set;
301
302 DEBUG3("Server core - Got EAGAIN (no buffer space left), waiting for pipe to become writable");
303
304 FD_ZERO(&error_set);
305 FD_ZERO(&write_set);
306
307 FD_SET(ofd->fd, &error_set);
308 FD_SET(ofd->fd, &write_set);
309
310 /*
311 * Don't let signals mess up the select
312 */
313 do {
314 ret = select(ofd->fd + 1, NULL, &write_set, &error_set, NULL);
315 } while ((ret == -1) && (errno == EINTR));
316
317 /*
318 * If there wasn't an error try again...
319 */
320 if ((ret > 0) && !FD_ISSET(ofd->fd, &error_set)) continue;
321 }
322
323 ERROR("Server core - Failed writing to pipe (%i): %s", ofd->fd, fr_syserror(errno));
324 return -1;
325 }
326
327 return 0;
328}
329
330/** Processes a request for a new pipe from a worker thread
331 *
332 * @param ofd for the main ctrl_pipe.
333 * @param what happened.
334 * @return
335 * - 0 on success, with pointer written to registration pipe for new osmo_fd.
336 * - -1 on error, with NULL pointer written to registration pipe.
337 */
338static int event_process_request(struct osmo_fd *ofd, unsigned int what)
339{
341
342 void *ptr;
343 ssize_t len;
344
345 if (what & BSC_FD_EXCEPT) {
346 ERROR("pipe (%i) closed by osmocom thread, event thread exiting", ofd->fd);
347 do_exit = true;
348 return -1;
349 }
350
351 if (!(what & BSC_FD_READ)) return 0;
352
353 len = read(ofd->fd, &ptr, sizeof(ptr));
354 if (len < 0) {
355 ERROR("osmocom thread - Failed reading from pipe (%i): %s", ofd->fd, fr_syserror(errno));
356 return -1;
357 }
358 if (len == 0) {
359 DEBUG4("Ignoring zero length read");
360 return 0;
361 }
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);
365 ptr = NULL;
366
367 if (sigtran_event_submit(ofd, NULL) < 0) {
368 fatal_error:
369 DEBUG3("Event loop will exit");
370 do_exit = true;
371 return -1;
372 }
373
374 return -1;
375 }
376
377 DEBUG3("osmocom thread - Read %zu bytes from pipe %i (%p)", len, ofd->fd, ptr);
378
379 txn = talloc_get_type_abort(ptr, sigtran_transaction_t);
380 txn->ctx.ofd = ofd;
381 switch (txn->request.type) {
383 {
384 struct osmo_fd *req_ofd;
385 int fd;
386
387 fd = *((int *)txn->request.data); /* Not talloced */
388
389 DEBUG3("osmocom thread - Registering req_pipe (%i)", fd);
390
391 req_ofd = ofd_create(ofd->data, fd, event_process_request, NULL);
392 if (!req_ofd) {
394 } else {
395 txn->response.type = SIGTRAN_RESPONSE_OK;
396 }
397 }
398 break;
399
401 DEBUG3("osmocom thread - Deregistering req_pipe (%i). Signalled by worker", ofd->fd);
402 txn->response.type = SIGTRAN_RESPONSE_OK;
403
404 if (sigtran_event_submit(ofd, txn) < 0) goto fatal_error;
405 talloc_free(ofd); /* Ordering is important */
406 return 0;
407
409 DEBUG3("osmocom thread - Bringing link up");
410 if (event_link_up(ofd->data, (sigtran_conn_t **)&txn->response.data, txn->request.data) < 0) { /* Struct not talloced */
412 } else {
413 txn->response.type = SIGTRAN_RESPONSE_OK;
414 }
415 break;
416
418 DEBUG3("osmocom thread - Taking link down");
419 if (event_link_down(talloc_get_type_abort(txn->request.data, sigtran_conn_t)) < 0) {
421 } else {
422 txn->response.type = SIGTRAN_RESPONSE_OK;
423 }
424 break;
425
427 {
428 sigtran_map_send_auth_info_req_t *req = talloc_get_type_abort(txn->request.data,
430 DEBUG3("osmocom thread - Processing map send auth info");
431 if (sigtran_tcap_outgoing(NULL, req->conn, txn, ofd) < 0) {
433 } else {
434 return 0; /* Keep caller blocked until we get a response */
435 }
436 }
437 break;
438
440 DEBUG3("osmocom thread - Event loop will exit");
441 do_exit = true;
442 txn->response.type = SIGTRAN_RESPONSE_OK;
443
444 if (sigtran_event_submit(ofd, txn) < 0) goto fatal_error;
445 talloc_free(ofd); /* Ordering is important */
446 return 0;
447
448#ifndef NDEBUG
450 txn->response.type = SIGTRAN_RESPONSE_OK;
451 break;
452#endif
453
454 default:
455 fr_assert(0);
456 goto fatal_error;
457 }
458
459 if (sigtran_event_submit(ofd, txn) < 0) goto fatal_error;
460
461 return 0;
462}
463
464/** Enter the libosmo event loop
465 *
466 * Will run until the thread is killed, or signalled to exit on the ctrl_pipe.
467 */
468static void *sigtran_event_loop(UNUSED void *instance)
469{
470 TALLOC_CTX *ctx = talloc_init_const("sigtran_event_ctx");
471
472 fr_assert((ctrl_pipe[0] < 0) && (ctrl_pipe[1] < 0)); /* Ensure only one instance exists */
473
474 /*
475 * Patch in libosmo's logging system to ours
476 */
477 sigtran_log_init(ctx);
478
479 if (socketpair(AF_UNIX, SOCK_STREAM, 0, ctrl_pipe) < 0) {
480 ERROR("osmocom thread - Failed creating ctrl_pipe: %s", fr_syserror(errno));
481 return NULL;
482 }
483 if (!ofd_create(ctx, ctrl_pipe[1], event_process_request, ctx)) return NULL;
484
485 DEBUG2("osmocom thread - Entering event loop, listening on fd %i (client fd %i)", ctrl_pipe[1], ctrl_pipe[0]);
486
487 sem_post(&event_thread_running); /* Up enough to be ok! */
488
489 /*
490 * The main event loop.
491 */
492 while (true) {
493 osmo_select_main(0);
494 if (do_exit) {
495#if 0
496 fd_set readset, writeset, exceptset;
497 int high_fd;
498
499 FD_ZERO(&readset);
500 FD_ZERO(&writeset);
501 FD_ZERO(&exceptset);
502
503 high_fd = osmo_fd_fill_fds(&readset, &writeset, &exceptset);
504 if (high_fd == 0) break;
505
506 DEBUG3("osmocom thread - Deferring exit, waiting for fd %i", high_fd);
507#else
508 break;
509#endif
510 }
511 }
512
513 talloc_free(ctx); /* Also frees ctrl pipe ofd (which closes ctrl_pipe[1]) */
514
515 DEBUG2("osmocom thread - Event loop exiting");
516
517 return NULL;
518}
519
520/** Start the libosmo event loop
521 *
522 */
524{
525 sigset_t sigmask;
526
527 sigemptyset(&sigmask);
528 sigaddset(&sigmask, SIGCHLD);
529
530 sem_init(&event_thread_running, 0, 0);
531
532 if (sigtran_sccp_global_init() < 0) {
533 ERROR("main thread - Failed initialising SCCP layer");
534 return -1;
535 }
536
537 /*
538 * Reset the signal mask some of the
539 * osmocom code seems to mess with it.
540 *
541 * This is so that old Linux kernels
542 * and libkqueue posix/proc work
543 * correctly.
544 */
545 pthread_sigmask(SIG_BLOCK, &sigmask, NULL);
546
548 ERROR("main thread - Failed spawning thread for multiplexer event loop: %s", fr_syserror(errno));
549 return -1;
550 }
551
552 sem_wait(&event_thread_running);
553
554#ifndef NDEBUG
555 {
557
558 txn = talloc_zero(NULL, sigtran_transaction_t);
559 txn->request.type = SIGTRAN_REQUEST_TEST;
560
561 if ((sigtran_client_do_transaction(ctrl_pipe[0], txn) < 0) ||
562 (txn->response.type != SIGTRAN_RESPONSE_OK)) {
563 ERROR("main thread - libosmo thread died");
564 talloc_free(txn);
565 return -1;
566 }
567 talloc_free(txn);
568
569 DEBUG2("main thread - libosmo thread responding");
570 }
571#endif
572
573 return 0;
574}
575
576/** Signal that libosmo should exit
577 *
578 */
580{
582
583 txn = talloc_zero(NULL, sigtran_transaction_t);
584 txn->request.type = SIGTRAN_REQUEST_EXIT;
585
586 if ((sigtran_client_do_transaction(ctrl_pipe[0], txn) < 0) || (txn->response.type != SIGTRAN_RESPONSE_OK)) {
587 ERROR("worker - Failed signalling osmocom thread to exit");
588 talloc_free(txn);
589 return -1;
590 }
591 talloc_free(txn);
592
593 close(ctrl_pipe[0]);
594 ctrl_pipe[0] = -1;
595 ctrl_pipe[1] = -1;
596
597 pthread_join(event_thread, NULL);
598
600
601 return 0;
602}
#define UNUSED
Definition build.h:318
#define MEM(x)
Definition debug.h:46
#define ERROR(fmt,...)
Definition dhcpclient.c:40
talloc_free(hp)
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:1399
#define DEBUG3(_fmt,...)
Definition log.h:266
#define DEBUG4(_fmt,...)
Definition log.h:267
long int ssize_t
unsigned char uint8_t
int ctrl_pipe[2]
Definition event.c:76
static sem_t event_thread_running
Definition event.c:78
static bool do_exit
Definition event.c:79
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:107
static pthread_t event_thread
Definition event.c:77
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:186
static int event_link_down(sigtran_conn_t *conn)
Take down a sigtran link.
Definition event.c:268
int sigtran_event_submit(struct osmo_fd *ofd, sigtran_transaction_t *txn)
Send response.
Definition event.c:281
static void * sigtran_event_loop(UNUSED void *instance)
Enter the libosmo event loop.
Definition event.c:468
int sigtran_event_start(void)
Start the libosmo event loop.
Definition event.c:523
int sigtran_event_exit(void)
Signal that libosmo should exit.
Definition event.c:579
int(* osmo_cb_func)(struct osmo_fd *fd, unsigned int what)
Definition event.c:81
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:338
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:137
static int _ofd_free(struct osmo_fd *ofd)
Unregister a osmocom_fd from the event loop, and close it.
Definition event.c:88
static int _mtp3_link_free(struct mtp_link *mtp3_link)
Shutdown the MTP3 link gracefully if it's being freed.
Definition event.c:128
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:37
#define DEBUG2(fmt,...)
static rs_t * conf
Definition radsniff.c:52
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:428
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::@191 request
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::@192 response
struct mtp_link * mtp3_link
Definition sigtran.h:185
struct sigtran_transaction::@193 ctx
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
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:120
#define talloc_strdup(_ctx, _str)
Definition talloc.h:142
static fr_slen_t data
Definition value.h:1340
static size_t char ** out
Definition value.h:1030