The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
client.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 #define LOG_PREFIX "sigtran"
28 
29 #include <freeradius-devel/server/base.h>
30 #include <freeradius-devel/util/debug.h>
31 #include <freeradius-devel/protocol/eap/aka-sim/dictionary.h>
32 #include <freeradius-devel/protocol/eap/aka-sim/dictionary.h>
33 #include <freeradius-devel/server/module_rlm.h>
34 
35 #include "attrs.h"
36 #include "sigtran.h"
37 
38 static pthread_mutex_t ctrl_pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
39 
40 /**
41  * $Id: a3b2e80bb4b1a6d92238adc714d04fa8b89bc3e0 $
42  * @file rlm_sigtran/client.c
43  * @brief Talk to the event loop.
44  */
46 {
47  ssize_t len;
48  void *ptr;
49 
50  if (write(fd, &txn, sizeof(txn)) < 0) {
51  ERROR("worker - ctrl_pipe (%i) write failed: %s", fd, fr_syserror(errno));
52  return -1;
53  }
54 
55  /*
56  * Block until libosmo responds
57  */
58  len = read(fd, &ptr, sizeof(ptr));
59  if (len < 0) {
60  ERROR("worker - ctrl_pipe (%i) read failed : %s", fd, fr_syserror(errno));
61  return -1;
62  }
63 
64  if (len != sizeof(ptr)) {
65  ERROR("worker - ctrl_pipe (%i) data too short, expected %zu bytes, got %zi bytes",
66  fd, sizeof(ptr), len);
67  return -1;
68  }
69 
70  if (ptr != txn) {
71  ERROR("worker - ctrl_pipe (%i) response ptr (%p) does not match request (%p)", fd, ptr, txn);
72  return -1;
73  }
74 
75  /*
76  * Check talloc header is still OK
77  */
78  talloc_get_type_abort(ptr, sigtran_transaction_t);
79 
80  return 0;
81 }
82 
84 {
85  int ret;
86 
87  fr_assert(ctrl_pipe[0] >= 0);
88 
89  pthread_mutex_lock(&ctrl_pipe_mutex);
91  pthread_mutex_unlock(&ctrl_pipe_mutex);
92 
93  return ret;
94 }
95 
96 /** This should never happen
97  *
98  */
99 static void _sigtran_pipe_error(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, int fd_errno, UNUSED void *uctx)
100 {
101  ERROR("worker - ctrl_pipe (%i) read failed : %s", fd, fr_syserror(fd_errno));
102  fr_assert(0);
103 }
104 
105 /** Drain any data we received
106  *
107  * We don't care about this data, we just don't want the kernel to
108  * signal the other side that our read buffer's full.
109  */
110 static void _sigtran_pipe_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, UNUSED void *uctx)
111 {
112  ssize_t len;
113  void *ptr;
115 
116  len = read(fd, &ptr, sizeof(ptr));
117  if (len < 0) {
118  ERROR("worker - ctrl_pipe (%i) read failed : %s", fd, fr_syserror(errno));
119  return;
120  }
121 
122  if (len != sizeof(ptr)) {
123  ERROR("worker - ctrl_pipe (%i) data too short, expected %zu bytes, got %zi bytes",
124  fd, sizeof(ptr), len);
125  return;
126  }
127 
128  /*
129  * Check talloc header is still OK
130  */
131  txn = talloc_get_type_abort(ptr, sigtran_transaction_t);
132  if (txn->ctx.defunct) return; /* Request was stopped */
133 
134  fr_assert(txn->ctx.request);
135  unlang_interpret_mark_runnable(txn->ctx.request); /* Continue processing */
136 }
137 
138 /** Called by a new thread to register a new req_pipe
139  *
140  * @return
141  * - The client side of the req_pipe on success.
142  * - -1 on error.
143  */
145 {
146  int req_pipe[2] = { -1, -1 };
148 
149  /*
150  * Create the pipe on our side, and pass over
151  * the remote end to be registered.
152  */
153  if (socketpair(AF_UNIX, SOCK_STREAM, 0, req_pipe) < 0) {
154  ERROR("worker - Failed creating req_pipe: %s", fr_syserror(errno));
155  return -1;
156  }
157 
158  fr_assert((req_pipe[0] >= 0) && (req_pipe[1] >= 0));
159 
160  txn = talloc_zero(NULL, sigtran_transaction_t);
162  txn->request.data = &req_pipe[1];
163 
164  if ((sigtran_client_do_ctrl_transaction(txn) < 0) || (txn->response.type != SIGTRAN_RESPONSE_OK)) {
165  ERROR("worker - Failed registering thread");
166  error:
167  close(req_pipe[0]);
168  close(req_pipe[1]);
169  talloc_free(txn);
170  return -1;
171  }
172  DEBUG3("worker - Thread register acked by osmocom thread");
173  talloc_free(txn);
174 
175  /*
176  * Read data coming back on the pipe,
177  * and resume requests which are
178  * waiting.
179  */
180  if (fr_event_fd_insert(NULL, NULL, el, req_pipe[0], _sigtran_pipe_read, NULL, _sigtran_pipe_error, NULL) < 0) {
181  ERROR("worker - Failed listening on osmocom pipe");
182  goto error;
183  }
184 
185  return req_pipe[0];
186 }
187 
188 /** Signal that libosmo should unregister the other side of the pipe
189  *
190  * @param[in] el the request pipe was registered to.
191  * @param[in] req_pipe_fd The rlm_sigtran side of the req_pipe.
192  */
194 {
196 
197  txn = talloc_zero(NULL, sigtran_transaction_t);
199 
200  /*
201  * The signal to unregister *MUST* be sent on the
202  * request pipe itself, so that the osmocom thread
203  * knows *WHICH* pipe to close on its side.
204  */
205  if ((sigtran_client_do_transaction(req_pipe_fd, txn) < 0) || (txn->response.type != SIGTRAN_RESPONSE_OK)) {
206  ERROR("worker - Failed unregistering thread");
207  talloc_free(txn);
208  return -1;
209  }
210  DEBUG3("worker - Thread unregister acked by osmocom thread");
211  talloc_free(txn);
212 
214  close(req_pipe_fd);
215 
216  return 0;
217 }
218 
219 /** Create a new connection
220  *
221  * Register the required links for a connection.
222  *
223  * @todo Return struct representing the connection
224  */
226 {
228 
229  txn = talloc_zero(NULL, sigtran_transaction_t);
230  txn->request.type = SIGTRAN_REQUEST_LINK_UP;
231  memcpy(&txn->request.data, &conn_conf, sizeof(txn->request.data));
232 
233  if ((sigtran_client_do_ctrl_transaction(txn) < 0) || (txn->response.type != SIGTRAN_RESPONSE_OK)) {
234  ERROR("worker - Failed bringing up link");
235  talloc_free(txn);
236  return -1;
237  }
238  DEBUG3("worker - Link up acked by osmocom thread");
239  *out = talloc_get_type_abort(txn->response.data, sigtran_conn_t);
240  talloc_free(txn);
241 
242  return 0;
243 }
244 
245 /** Destroy a connection
246  *
247  * Gracefully shutdown the links for a connection and free it.
248  *
249  */
251 {
253 
254  if (!*conn || !(*conn)->mtp3_link) return 0; /* Ignore if there is no link */
255 
256  txn = talloc_zero(NULL, sigtran_transaction_t);
258  memcpy(&txn->request.data, conn, sizeof(txn->request.data));
259 
260  if ((sigtran_client_do_ctrl_transaction(txn) < 0) || (txn->response.type != SIGTRAN_RESPONSE_OK)) {
261  ERROR("worker - Failed taking down the link");
262  talloc_free(txn);
263  return -1;
264  }
265  DEBUG3("worker - Link down acked by osmocom thread");
266  talloc_free(txn);
267  *conn = NULL;
268 
269  return 0;
270 }
271 
272 static void sigtran_client_signal(module_ctx_t const *mctx, UNUSED request_t *request, UNUSED fr_signal_t action)
273 {
274  sigtran_transaction_t *txn = talloc_get_type_abort(mctx->rctx, sigtran_transaction_t);
275 
276  txn->ctx.defunct = true; /* Mark the transaction up as needing to be freed */
277  txn->ctx.request = NULL; /* remove the link to the (now dead) request */
278 }
279 
281 {
282  sigtran_transaction_t *txn = talloc_get_type_abort(mctx->rctx, sigtran_transaction_t);
283  rlm_rcode_t rcode;
284  fr_assert(request == txn->ctx.request);
285 
286  /*
287  * Process response
288  */
289  switch (txn->response.type) {
290  case SIGTRAN_RESPONSE_OK:
291  {
292  unsigned int i = 0;
293  fr_pair_t *vp;
294  sigtran_vector_t *vec;
295  sigtran_map_send_auth_info_res_t *res = talloc_get_type_abort(txn->response.data,
297 
298  for (vec = res->vector; vec; vec = vec->next) {
299  switch (vec->type) {
301  fr_assert(vec->sim.rand);
302  fr_assert(vec->sim.sres);
303  fr_assert(vec->sim.kc);
304 
305  RDEBUG2("SIM auth vector %i", i);
306  RINDENT();
307  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_rand));
308  MEM(fr_pair_value_memdup_buffer(vp, vec->sim.rand, true) == 0);
309  TALLOC_FREE(vec->sim.rand);
310  RDEBUG2("&control.%pP", vp);
311  fr_pair_append(&request->control_pairs, vp);
312 
313  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_sres));
314  MEM(fr_pair_value_memdup_buffer(vp, vec->sim.sres, true) == 0);
315  TALLOC_FREE(vec->sim.sres);
316  RDEBUG2("&control.%pP", vp);
317  fr_pair_append(&request->control_pairs, vp);
318 
319  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_kc));
320  MEM(fr_pair_value_memdup_buffer(vp, vec->sim.kc, true) == 0);
321  TALLOC_FREE(vec->sim.kc);
322  RDEBUG2("&control.%pP", vp);
323  fr_pair_append(&request->control_pairs, vp);
324  REXDENT();
325 
326  i++;
327  break;
328 
330  fr_assert(vec->umts.rand);
331  fr_assert(vec->umts.xres);
332  fr_assert(vec->umts.ck);
333  fr_assert(vec->umts.ik);
334  fr_assert(vec->umts.authn);
335 
336  RDEBUG2("UMTS auth vector %i", i);
337  RINDENT();
338  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_rand));
339  MEM(fr_pair_value_memdup_buffer(vp, vec->umts.rand, true) == 0);
340  TALLOC_FREE(vec->umts.rand);
341  RDEBUG2("&control.%pP", vp);
342  fr_pair_append(&request->control_pairs, vp);
343 
344  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_xres));
345  MEM(fr_pair_value_memdup_buffer(vp, vec->umts.xres, true) == 0);
346  TALLOC_FREE(vec->umts.xres);
347  RDEBUG2("&control.%pP", vp);
348  fr_pair_append(&request->control_pairs, vp);
349 
350  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_ck));
351  MEM(fr_pair_value_memdup_buffer(vp, vec->umts.ck, true) == 0);
352  TALLOC_FREE(vec->umts.ck);
353  RDEBUG2("&control.%pP", vp);
354  fr_pair_append(&request->control_pairs, vp);
355 
356  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_ik));
357  MEM(fr_pair_value_memdup_buffer(vp, vec->umts.ik, true) == 0);
358  TALLOC_FREE(vec->umts.ik);
359  RDEBUG2("&control.%pP", vp);
360  fr_pair_append(&request->control_pairs, vp);
361 
362  MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_autn));
363  MEM(fr_pair_value_memdup_buffer(vp, vec->umts.authn, true) == 0);
364  TALLOC_FREE(vec->umts.authn);
365  RDEBUG2("&control.%pP", vp);
366  fr_pair_append(&request->control_pairs, vp);
367  REXDENT();
368 
369  i++;
370  break;
371  }
372  }
373  rcode = RLM_MODULE_OK;
374  }
375  break;
376 
378  rcode = RLM_MODULE_NOOP;
379  break;
380 
382  rcode = RLM_MODULE_NOTFOUND;
383  break;
384 
385  default:
386  fr_assert(0);
387  FALL_THROUGH;
388 
390  rcode = RLM_MODULE_FAIL;
391  break;
392  }
393  talloc_free(txn);
394 
395  RETURN_MODULE_RCODE(rcode);
396 }
397 
398 /** Create a MAP_SEND_AUTH_INFO request
399  *
400  * @param p_result Where to write the result.
401  * @param inst of rlm_sigtran.
402  * @param request The current request.
403  * @param conn current connection.
404  * @param fd file descriptor on which the transaction is done
405  */
407  sigtran_conn_t const *conn, int fd)
408 {
411  char *imsi;
412  size_t len;
413 
414  fr_assert((fd != ctrl_pipe[0]) && (fd != ctrl_pipe[1]));
415 
416  txn = talloc_zero(NULL, sigtran_transaction_t);
418 
419  req = talloc(txn, sigtran_map_send_auth_info_req_t);
420  req->conn = conn;
421 
422  if (tmpl_aexpand(request, &req->version, request, inst->conn_conf.map_version, NULL, NULL) < 0) {
423  ERROR("Failed retrieving version");
424  error:
425  talloc_free(txn);
427  }
428 
429  switch (req->version) {
430  case 2:
431  case 3:
432  break;
433 
434  default:
435  REDEBUG("%i is not a valid version", req->version);
436  goto error;
437  }
438 
439  txn->request.data = req;
440  txn->ctx.request = request;
441 
442  if (tmpl_aexpand(req, &imsi, request, inst->imsi, NULL, NULL) < 0) {
443  REDEBUG("Failed retrieving IMSI");
444  goto error;
445  }
446 
447  len = talloc_array_length(imsi) - 1;
448  if ((len != 16) && (len != 15)) {
449  REDEBUG("IMSI must be 15 or 16 digits got %zu digits", len);
450  goto error;
451  }
452 
453  if (sigtran_ascii_to_tbcd(req, &req->imsi, imsi) < 0) {
454  REDEBUG("Failed converting ASCII to BCD");
455  goto error;
456  }
457 
458  if (RDEBUG_ENABLED2) {
459  RDEBUG2("Sending MAPv%u request with IMSI \"%pV\"", req->version, fr_box_strvalue_buffer(imsi));
460  } else if (RDEBUG_ENABLED3){
461  RDEBUG3("Sending MAPv%u request with IMSI \"%pV\" (TBCD %pV)",
463  }
464 
465  /*
466  * FIXME - We shouldn't assume the pipe is always writable
467  */
468  if (write(fd, &txn, sizeof(txn)) < 0) {
469  REDEBUG("worker - ctrl_pipe (%i) write failed: %s", fd, fr_syserror(errno));
470  goto error;
471  }
472 
473  return unlang_module_yield(request, sigtran_client_map_resume, sigtran_client_signal, ~FR_SIGNAL_CANCEL, txn);
474 }
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define UNUSED
Definition: build.h:313
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
#define fr_event_fd_insert(...)
Definition: event.h:232
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition: event.h:62
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
Definition: interpret.c:1359
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_xres
Definition: base.c:101
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_sres
Definition: base.c:98
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_ik
Definition: base.c:75
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_autn
Definition: base.c:61
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_kc
Definition: base.c:80
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_ck
Definition: base.c:65
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_rand
Definition: attrs.h:39
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:443
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition: log.h:335
#define RDEBUG3(fmt,...)
Definition: log.h:343
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:430
talloc_free(reap)
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition: event.c:1260
Stores all information relating to an event list.
Definition: event.c:411
long int ssize_t
Definition: merged_model.c:24
void * rctx
Resume ctx that a module previously set.
Definition: module_ctx.h:45
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
int ctrl_pipe[2]
Definition: event.c:78
int fr_pair_value_memdup_buffer(fr_pair_t *vp, uint8_t const *src, bool tainted)
Copy data from a talloced buffer into an "octets" data type.
Definition: pair.c:3011
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:283
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition: pair.c:1345
VQP attributes.
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG_ENABLED2()
Definition: radclient.h:50
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define RETURN_MODULE_RCODE(_rcode)
Definition: rcode.h:64
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
@ RLM_MODULE_NOTFOUND
User not found.
Definition: rcode.h:47
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
#define tmpl_aexpand(_ctx, _out, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, allocing a new buffer to hold the string.
Definition: tmpl.h:1070
fr_signal_t
Definition: signal.h:48
int sigtran_ascii_to_tbcd(TALLOC_CTX *ctx, uint8_t **out, char const *digits)
Definition: sigtran.c:93
Declarations for various sigtran functions.
@ SIGTRAN_VECTOR_TYPE_UMTS_QUINTUPLETS
RAND, XRES, CK, IK, AUTN.
Definition: sigtran.h:66
@ SIGTRAN_VECTOR_TYPE_SIM_TRIPLETS
RAND, SRES, Kc.
Definition: sigtran.h:65
@ 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_LINK_UP
Bring up a link.
Definition: sigtran.h:45
@ SIGTRAN_RESPONSE_OK
Request succeeded.
Definition: sigtran.h:55
@ SIGTRAN_RESPONSE_NOOP
Request did nothing.
Definition: sigtran.h:56
@ SIGTRAN_RESPONSE_FAIL
Request failed.
Definition: sigtran.h:58
@ SIGTRAN_RESPONSE_NOTFOUND
User or device Not found.
Definition: sigtran.h:57
uint8_t * imsi
BCD encoded IMSI.
Definition: sigtran.h:193
struct sigtran_transaction::@173 response
sigtran_vector_type_t type
Type of vector returned.
Definition: sigtran.h:218
sigtran_conn_t const * conn
Connection to send request on.
Definition: sigtran.h:192
uint8_t version
Application context version.
Definition: sigtran.h:194
struct sigtran_transaction::@172 request
struct sigtran_transaction::@174 ctx
struct mtp_link * mtp3_link
Definition: sigtran.h:185
sigtran_vector_t * vector
Linked list of vectors.
Definition: sigtran.h:228
sigtran_vector_t * next
Next vector in list.
Definition: sigtran.h:220
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
MAP send auth info response.
Definition: sigtran.h:226
Request and response from the event loop.
Definition: sigtran.h:75
Authentication vector returned by HLR.
Definition: sigtran.h:203
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition: module.c:419
int sigtran_client_thread_register(fr_event_list_t *el)
Called by a new thread to register a new req_pipe.
Definition: client.c:144
unlang_action_t sigtran_client_map_send_auth_info(rlm_rcode_t *p_result, rlm_sigtran_t const *inst, request_t *request, sigtran_conn_t const *conn, int fd)
Create a MAP_SEND_AUTH_INFO request.
Definition: client.c:406
static unlang_action_t sigtran_client_map_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: client.c:280
int sigtran_client_link_up(sigtran_conn_t const **out, sigtran_conn_conf_t const *conn_conf)
Create a new connection.
Definition: client.c:225
int sigtran_client_thread_unregister(fr_event_list_t *el, int req_pipe_fd)
Signal that libosmo should unregister the other side of the pipe.
Definition: client.c:193
int sigtran_client_link_down(sigtran_conn_t const **conn)
Destroy a connection.
Definition: client.c:250
static void _sigtran_pipe_error(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, int fd_errno, UNUSED void *uctx)
This should never happen.
Definition: client.c:99
static void _sigtran_pipe_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, UNUSED void *uctx)
Drain any data we received.
Definition: client.c:110
static void sigtran_client_signal(module_ctx_t const *mctx, UNUSED request_t *request, UNUSED fr_signal_t action)
Definition: client.c:272
int sigtran_client_do_transaction(int fd, sigtran_transaction_t *txn)
Definition: client.c:45
static int sigtran_client_do_ctrl_transaction(sigtran_transaction_t *txn)
Definition: client.c:83
static pthread_mutex_t ctrl_pipe_mutex
Definition: client.c:38
RETURN_MODULE_FAIL
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
close(uq->fd)
static fr_event_list_t * el
#define fr_box_strvalue_buffer(_val)
Definition: value.h:289
#define fr_box_octets_buffer(_val)
Definition: value.h:290
static size_t char ** out
Definition: value.h:997