The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
radius1_test.c
Go to the documentation of this file.
1 /*
2  * radius_test.c Tests for channels
3  *
4  * Version: $Id: 8fd3b9be6e033327bce66dc34c4054afcfd8cc12 $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * @copyright 2016 Alan DeKok (aland@freeradius.org)
21  */
22 
23 RCSID("$Id: 8fd3b9be6e033327bce66dc34c4054afcfd8cc12 $")
24 
25 #include <freeradius-devel/io/control.h>
26 #include <freeradius-devel/io/listen.h>
27 #include <freeradius-devel/io/worker.h>
28 #include <freeradius-devel/radius/defs.h>
29 #include <freeradius-devel/util/debug.h>
30 #include <freeradius-devel/util/inet.h>
31 #include <freeradius-devel/util/log.h>
32 #include <freeradius-devel/util/md5.h>
33 #include <freeradius-devel/util/syserror.h>
34 
35 #ifdef HAVE_GETOPT_H
36 # include <getopt.h>
37 #endif
38 
39 #include <pthread.h>
40 #include <signal.h>
41 
42 #include <sys/event.h>
43 
44 #define MAX_MESSAGES (2048)
45 #define MAX_CONTROL_PLANE (1024)
46 #define MAX_KEVENTS (10)
47 #define MAX_WORKERS (1024)
48 
49 #define MPRINT1 if (debug_lvl) printf
50 #define MPRINT2 if (debug_lvl > 1) printf
51 
52 
53 typedef struct {
54  int id; //!< ID of the worker 0..N
55  pthread_t pthread_id; //!< pthread ID of the worker
56  fr_worker_t *worker; //!< pointer to the worker
57  fr_channel_t *ch; //!< channel for communicating with the worker
59 
60 typedef struct {
61  uint8_t vector[16];
63 
64  struct sockaddr_storage src;
65  socklen_t salen;
67 
68 static int debug_lvl = 0;
69 static int max_control_plane = 0;
70 static int num_workers = 1;
71 static bool quiet = false;
72 
75 static char const *secret = "testing123";
76 
78 
79 static NEVER_RETURNS void usage(void)
80 {
81  fprintf(stderr, "usage: radius_test [OPTS]\n");
82  fprintf(stderr, " -c <control-plane> Size of the control plane queue.\n");
83  fprintf(stderr, " -i <address>[:port] Set IP address and optional port.\n");
84  fprintf(stderr, " -q quiet - suppresses worker stats.\n");
85  fprintf(stderr, " -s <secret> Set shared secret.\n");
86  fprintf(stderr, " -w N Create N workers. Default is 1.\n");
87  fprintf(stderr, " -x Debugging mode.\n");
88 
89  fr_exit_now(EXIT_FAILURE);
90 }
91 
92 static rlm_rcode_t test_process(UNUSED void const *instance, request_t *request, fr_io_action_t action)
93 {
94  MPRINT1("\t\tPROCESS --- request %"PRIu64" action %d\n", request->number, action);
96 }
97 
98 
99 static int test_decode(UNUSED void const *instance, request_t *request, uint8_t *const data, size_t data_len)
100 {
101  fr_packet_ctx_t const *pc = talloc_get_type_abort_const(request->async->listen->app_instance,
103 
104  request->number = pc->id;
105  request->async->process = test_process;
106 
107  if (!debug_lvl) return 0;
108 
109  MPRINT1("\t\tDECODE <<< request %"PRIu64" - %p data %p size %zd\n", request->number, pc, data, data_len);
110 
111  return 0;
112 }
113 
114 static ssize_t test_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
115 {
116  fr_md5_ctx_t *md5_ctx;
117  fr_packet_ctx_t const *pc = talloc_get_type_abort_const(request->async->listen->app_instance,
119 
120  MPRINT1("\t\tENCODE >>> request %"PRIu64" - data %p %p room %zd\n",
121  request->number, pc, buffer, buffer_len);
122 
124  buffer[1] = pc->id;
125  buffer[2] = 0;
126  buffer[3] = 20;
127 
128  memcpy(buffer + 4, pc->vector, 16);
129 
130  md5_ctx = fr_md5_ctx_alloc_from_list();
131  fr_md5_update(md5_ctx, buffer, 20);
132  fr_md5_update(md5_ctx, (uint8_t const *) secret, strlen(secret));
133  fr_md5_final(buffer + 4, md5_ctx);
134  fr_md5_ctx_free_from_list(&md5_ctx);
135 
136  return 20;
137 }
138 
139 static size_t test_nak(void const *instance, UNUSED void *packet_ctx, uint8_t *const packet, size_t packet_len, UNUSED uint8_t *reply, UNUSED size_t reply_len)
140 {
141  MPRINT1("\t\tNAK !!! request %d - data %p %p size %zd\n", packet[1], instance, packet, packet_len);
142 
143  return 10;
144 }
145 
146 static fr_app_io_t app_io = {
147  .name = "worker-test",
148  .default_message_size = 4096,
149  .nak = test_nak,
150  .encode = test_encode,
151  .decode = test_decode
152 };
153 
154 static void *worker_thread(void *arg)
155 {
156  TALLOC_CTX *ctx;
157  fr_worker_t *worker;
160 
161  sw = (fr_schedule_worker_t *) arg;
162 
163  MPRINT1("\tWorker %d started.\n", sw->id);
164 
165  MEM(ctx = talloc_init_const("worker"));
166 
167  el = fr_event_list_alloc(ctx, NULL, NULL);
168  if (!el) {
169  fprintf(stderr, "radius_test: Failed to create the event list\n");
170  fr_exit_now(EXIT_FAILURE);
171  }
172 
173  worker = sw->worker = fr_worker_create(ctx, el, "test", &default_log, L_DBG_LVL_MAX);
174  if (!worker) {
175  fprintf(stderr, "radius_test: Failed to create the worker\n");
176  fr_exit_now(EXIT_FAILURE);
177  }
178 
179  MPRINT1("\tWorker %d looping.\n", sw->id);
180  fr_worker(worker);
181 
182  sw->worker = NULL;
183  MPRINT1("\tWorker %d exiting.\n", sw->id);
184 
185  talloc_free(ctx);
186  return NULL;
187 }
188 
189 
190 static void send_reply(int sockfd, fr_channel_data_t *reply)
191 {
192  fr_packet_ctx_t *pc = talloc_get_type_abort(reply->packet_ctx, fr_packet_ctx_t);
193 
194  MPRINT1("Master got reply %d size %zd\n", pc->id, reply->m.data_size);
195 
196  if (sendto(sockfd, reply->m.data, reply->m.data_size, 0, (struct sockaddr *) &pc->src, pc->salen) < 0) {
197  fprintf(stderr, "Failed sending reply: %s\n", fr_syserror(errno));
198  fr_exit_now(EXIT_FAILURE);
199  }
200 
201  talloc_free(pc);
202 
203  fr_message_done(&reply->m);
204 }
205 
206 
207 static void master_process(TALLOC_CTX *ctx)
208 {
209  bool running;
210  int rcode, i, num_events, which_worker;
211  int num_outstanding;
212  fr_message_set_t *ms;
213  fr_channel_t *ch;
215  pthread_attr_t pthread_attr;
217  struct kevent events[MAX_KEVENTS];
218  int kq_master;
221  fr_listen_t listen = { .app_io = &app_io };
222  int sockfd;
223 
224  MPRINT1("Master started.\n");
225 
227  if (!ms) {
228  fprintf(stderr, "Failed creating message set\n");
229  fr_exit_now(EXIT_FAILURE);
230  }
231 
232  /*
233  * Create the KQ and associated sockets.
234  */
235  kq_master = kqueue();
236  fr_assert(kq_master >= 0);
237 
239  fr_assert(aq_master != NULL);
240 
242  fr_assert(control_master != NULL);
243 
244  sockfd = fr_socket_server_udp(&my_ipaddr, &my_port, NULL, true);
245  if (sockfd < 0) {
246  fr_perror("radius_test: Failed creating socket");
247  fr_exit_now(EXIT_FAILURE);
248  }
249 
250  if (fr_socket_bind(sockfd, NULL, &my_ipaddr, &my_port) < 0) {
251  fr_perror("radius_test: Failed binding to socket");
252  fr_exit_now(EXIT_FAILURE);
253  }
254 
255  /*
256  * Set up the KQ filter for reading.
257  */
258  EV_SET(&events[0], sockfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
259  if (kevent(kq_master, events, 1, NULL, 0, NULL) < 0) {
260  fr_perror("Failed setting KQ for EVFILT_READ");
261  fr_exit_now(EXIT_FAILURE);
262  }
263 
264  /*
265  * Create the worker threads.
266  */
267  (void) pthread_attr_init(&pthread_attr);
268  (void) pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_JOINABLE);
269 
270  for (i = 0; i < num_workers; i++) {
271  workers[i].id = i;
272  (void) pthread_create(&workers[i].pthread_id, &pthread_attr, worker_thread, &workers[i]);
273  }
274 
275  MPRINT1("Master created %d workers.\n", num_workers);
276 
277  /*
278  * Busy loop because that's fine for the test
279  */
280  num_outstanding = 0;
281  while (num_outstanding < num_workers) {
282  for (i = 0; i < num_workers; i++) {
283  if (!workers[i].worker) continue;
284  if (workers[i].ch != NULL) continue;
285 
286  /*
287  * Create the channel and signal the
288  * worker that it is open
289  */
290  MPRINT1("Master creating channel to worker %d.\n", num_workers);
292  fr_assert(workers[i].ch != NULL);
293 
294  (void) fr_channel_master_ctx_add(workers[i].ch, &workers[i]);
295 
296  num_outstanding++;
297  }
298  }
299 
300  MPRINT1("Master created all channels.\n");
301 
302  which_worker = 0;
303  running = true;
304 
305  while (running) {
306  bool control_plane_signal;
307  fr_time_t now;
308  fr_channel_data_t *cd, *reply;
309 
310  MPRINT1("Master waiting on events.\n");
311 
312  num_events = kevent(kq_master, NULL, 0, events, MAX_KEVENTS, NULL);
313  MPRINT1("Master kevent returned %d\n", num_events);
314 
315  if (num_events < 0) {
316  if (errno == EINTR) continue;
317 
318  fprintf(stderr, "Failed waiting for kevent: %s\n", fr_syserror(errno));
319  fr_exit_now(EXIT_FAILURE);
320  }
321 
322  if (num_events == 0) continue;
323 
324  control_plane_signal = false;
325 
326  /*
327  * Service the events.
328  *
329  * @todo this should NOT take a channel pointer
330  */
331  for (i = 0; i < num_events; i++) {
332  uint8_t *packet, *attr, *end;
333  size_t total_len;
334  ssize_t data_size;
335  fr_packet_ctx_t *packet_ctx;
336 
337  if (events[i].filter == EVFILT_USER) {
339  control_plane_signal = true;
340  break;
341  }
342 
343  fr_assert(events[i].filter == EVFILT_READ);
344 
345  cd = (fr_channel_data_t *) fr_message_reserve(ms, 4096);
346  fr_assert(cd != NULL);
347 
348  packet_ctx = talloc(ctx, fr_packet_ctx_t);
349  fr_assert(packet_ctx != NULL);
350  packet_ctx->salen = sizeof(packet_ctx->src);
351 
352  cd->priority = 0;
353  cd->packet_ctx = packet_ctx;
354  cd->listen = &listen;
355 
356  data_size = recvfrom(sockfd, cd->m.data, cd->m.rb_size, 0,
357  (struct sockaddr *) &packet_ctx->src, &packet_ctx->salen);
358  MPRINT1("Master got packet size %zd\n", data_size);
359  if (data_size <= 20) {
360  MPRINT1("Master ignoring packet (data length %zd)\n", data_size);
361 
362  discard:
363  fr_message_done(&cd->m); /* yeah, reuse it for the next packet... */
364  continue;
365  }
366 
367  /*
368  * Verify the packet before doing anything more with it.
369  */
370  packet = cd->m.data;
371  if (packet[0] != FR_RADIUS_CODE_ACCESS_REQUEST) {
372  MPRINT1("Master ignoring packet code %u\n", packet[0]);
373  goto discard;
374  }
375 
376  total_len = fr_nbo_to_uint16(packet + 2);
377  if (total_len < 20) {
378  MPRINT1("Master ignoring packet (header length %zu)\n", total_len);
379  goto discard;
380  }
381  if (total_len > (size_t) data_size) {
382  MPRINT1("Master ignoring truncated packet (read %zd, says %zu)\n",
383  data_size, total_len);
384  goto discard;
385  }
386 
387  attr = packet + 20;
388  end = packet + data_size;
389  while (attr < end) {
390  if ((end - attr) < 2) goto discard;
391  if (attr[0] == 0) goto discard;
392  if (attr[1] < 2) goto discard;
393  if ((attr + attr[1]) > end) goto discard;
394 
395  attr += attr[1];
396  }
397 
398  (void) fr_message_alloc(ms, &cd->m, total_len);
399 
400  MPRINT1("Master sending packet size %zd to worker %d\n", cd->m.data_size, which_worker);
401  cd->m.when = fr_time();
402 
403  packet_ctx->id = packet[1];
404  memcpy(packet_ctx->vector, packet + 4, 16);
405 
406  rcode = fr_channel_send_request(workers[which_worker].ch, cd, &reply);
407  if (rcode < 0) {
408  fprintf(stderr, "Failed sending request: %s\n", fr_syserror(errno));
409  fr_exit_now(EXIT_FAILURE);
410  }
411  which_worker++;
412  if (which_worker >= num_workers) which_worker = 0;
413 
414  fr_assert(rcode == 0);
415  if (reply) send_reply(sockfd, reply);
416  }
417 
418  if (!control_plane_signal) continue;
419 
420  now = fr_time();
421 
422  MPRINT1("Master servicing control-plane\n");
423 
424  while (true) {
425  uint32_t id;
426  size_t data_size;
427  char data[256];
428 
429  data_size = fr_control_message_pop(aq_master, &id, data, sizeof(data));
430  if (!data_size) break;
431 
433 
434  ce = fr_channel_service_message(now, &ch, data, data_size);
435  MPRINT1("Master got channel event %d\n", ce);
436 
437  switch (ce) {
439  MPRINT1("Master got data ready signal\n");
440 
441  reply = fr_channel_recv_reply(ch);
442  if (!reply) {
443  MPRINT1("Master SIGNAL WITH NO DATA!\n");
444  continue;
445  }
446 
447  do {
448  send_reply(sockfd, reply);
449  } while ((reply = fr_channel_recv_reply(ch)) != NULL);
450  break;
451 
452  case FR_CHANNEL_CLOSE:
453  sw = fr_channel_master_ctx_get(ch);
454  fr_assert(sw != NULL);
455 
456  MPRINT1("Master received close ack signal for worker %d\n", sw->id);
457 
458  (void) pthread_kill(sw->pthread_id, SIGTERM);
459  running = false;
460  break;
461 
462  case FR_CHANNEL_NOOP:
463  break;
464 
465  default:
466  fprintf(stderr, "Master got unexpected CE %d\n", ce);
467 
468  /*
469  * Not written yet!
470  */
471  fr_assert(0 == 1);
472  break;
473  } /* switch over signal returned */
474  } /* drain the control plane */
475  } /* loop until told to exit */
476 
477  MPRINT1("Master exiting.\n");
478 
479  fr_time_t last_checked = fr_time();
480 
481  /*
482  * Busy-wait for the workers to exit;
483  */
484  do {
485  fr_time_t now = fr_time();
486 
487  num_outstanding = num_workers;
488 
489  for (i = 0; i < num_workers; i++) {
490  if (!workers[i].worker) num_outstanding--;
491  }
492 
493  if ((now - last_checked) > (NSEC / 10)) {
494  MPRINT1("still num_outstanding %d\n", num_outstanding);
495  }
496 
497  } while (num_outstanding > 0);
498 
499  /*
500  * Force all messages to be garbage collected
501  */
502  MPRINT2("GC\n");
503  fr_message_set_gc(ms);
504 
505  if (debug_lvl > 1) fr_message_set_debug(ms, stdout);
506 
507  /*
508  * After the garbage collection, all messages marked "done" MUST also be marked "free".
509  */
510  rcode = fr_message_set_messages_used(ms);
511  MPRINT2("Master messages used = %d\n", rcode);
512  fr_assert(rcode == 0);
513  close(sockfd);
514 }
515 
516 static void sig_ignore(int sig)
517 {
518  (void) signal(sig, sig_ignore);
519 }
520 
521 int main(int argc, char *argv[])
522 {
523  int c;
524  TALLOC_CTX *autofree = talloc_autofree_context();
525  uint16_t port16 = 0;
526 
527  fr_time_start();
528 
530 
531  memset(&my_ipaddr, 0, sizeof(my_ipaddr));
532  my_ipaddr.af = AF_INET;
533  my_ipaddr.prefix = 32;
534  my_ipaddr.addr.v4.s_addr = htonl(INADDR_LOOPBACK);
535  my_port = 1812;
536 
537  while ((c = getopt(argc, argv, "c:hi:qs:w:x")) != -1) switch (c) {
538  case 'x':
539  debug_lvl++;
540  break;
541 
542  case 'c':
543  max_control_plane = atoi(optarg);
544  break;
545 
546  case 'i':
547  if (fr_inet_pton_port(&my_ipaddr, &port16, optarg, -1, AF_INET, true, false) < 0) {
548  fr_perror("Failed parsing ipaddr");
549  fr_exit_now(EXIT_FAILURE);
550  }
551  my_port = port16;
552  break;
553 
554  case 'q':
555  quiet = true;
556  break;
557 
558  case 's':
559  secret = optarg;
560  break;
561 
562  case 'w':
563  num_workers = atoi(optarg);
564  if ((num_workers <= 0) || (num_workers >= MAX_WORKERS)) usage();
565  break;
566 
567  case 'h':
568  default:
569  usage();
570  }
571 
572  if (!max_control_plane) {
575  }
576 
577 #if 0
578  argc -= (optind - 1);
579  argv += (optind - 1);
580 #endif
581 
582  signal(SIGTERM, sig_ignore);
583 
584  if (debug_lvl) {
585  setvbuf(stdout, NULL, _IONBF, 0);
586  }
587 
589 
590  fr_exit_now(EXIT_SUCCESS);
591 }
static int const char char buffer[256]
Definition: acutest.h:574
size_t default_message_size
Usually maximum message size.
Definition: app_io.h:39
Public structure describing an I/O path for a protocol.
Definition: app_io.h:33
fr_atomic_queue_t * fr_atomic_queue_alloc(TALLOC_CTX *ctx, size_t size)
Create fixed-size atomic queue.
Definition: atomic_queue.c:80
Structure to hold the atomic queue.
Definition: atomic_queue.c:54
#define RCSID(id)
Definition: build.h:444
#define NEVER_RETURNS
Should be placed before the function return type.
Definition: build.h:311
#define UNUSED
Definition: build.h:313
bool fr_channel_recv_reply(fr_channel_t *ch)
Receive a reply message from the channel.
Definition: channel.c:408
int fr_channel_send_request(fr_channel_t *ch, fr_channel_data_t *cd)
Send a request message into the channel.
Definition: channel.c:306
fr_channel_event_t fr_channel_service_message(fr_time_t when, fr_channel_t **p_channel, void const *data, size_t data_size)
Service a control-plane message.
Definition: channel.c:685
int fr_channel_service_kevent(fr_channel_t *ch, fr_control_t *c, UNUSED struct kevent const *kev)
Service a control-plane event.
Definition: channel.c:788
A full channel, which consists of two ends.
Definition: channel.c:144
fr_message_t m
the message header
Definition: channel.h:105
fr_channel_event_t
Definition: channel.h:67
@ FR_CHANNEL_NOOP
Definition: channel.h:74
@ FR_CHANNEL_CLOSE
Definition: channel.h:72
@ FR_CHANNEL_DATA_READY_REQUESTOR
Definition: channel.h:70
void * packet_ctx
Packet specific context for holding client information, and other proto_* specific information that n...
Definition: channel.h:142
fr_listen_t * listen
for tracking packet transport, etc.
Definition: channel.h:146
uint32_t priority
Priority of this packet.
Definition: channel.h:140
Channel information which is added to a message.
Definition: channel.h:104
static fr_atomic_queue_t * aq_master
Definition: channel_test.c:47
static fr_control_t * control_master
Definition: channel_test.c:48
static int kq_master
Definition: channel_test.c:46
#define FR_CONTROL_ID_CHANNEL
Definition: control.h:56
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition: debug.h:232
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition: defs.h:33
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition: defs.h:34
static int sockfd
Definition: dhcpclient.c:56
int fr_inet_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, int af, bool resolve, bool mask)
Parses IPv4/6 address + port, to fr_ipaddr_t and integer (port)
Definition: inet.c:923
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
Definition: inet.h:69
int af
Address family.
Definition: inet.h:64
union fr_ipaddr_t::@121 addr
IPv4/6 prefix.
Definition: merged_model.c:272
ssize_t fr_control_message_pop(fr_atomic_queue_t *aq, uint32_t *p_id, void *data, size_t data_size)
Pop control-plane message.
Definition: control.c:377
fr_control_t * fr_control_create(TALLOC_CTX *ctx, fr_event_list_t *el, fr_atomic_queue_t *aq)
Create a control-plane signaling path.
Definition: control.c:149
The control structure.
Definition: control.c:79
fr_app_io_t const * app_io
I/O path functions.
Definition: listen.h:31
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
Initialise a new event list.
Definition: event.c:2892
talloc_free(reap)
Stores all information relating to an event list.
Definition: event.c:411
int fr_log_init_legacy(fr_log_t *log, bool daemonize)
Initialise file descriptors based on logging destination.
Definition: log.c:923
fr_log_t default_log
Definition: log.c:290
@ L_DBG_LVL_MAX
Lowest priority debug messages (-xxxxx | -Xxxx).
Definition: log.h:74
fr_md5_update_t fr_md5_update
Definition: md5.c:450
fr_md5_final_t fr_md5_final
Definition: md5.c:451
void fr_md5_ctx_free_from_list(fr_md5_ctx_t **ctx)
Definition: md5.c:530
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
Definition: md5.c:485
void fr_md5_ctx_t
Definition: md5.h:28
unsigned short uint16_t
Definition: merged_model.c:31
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
fr_message_set_t * fr_message_set_create(TALLOC_CTX *ctx, int num_messages, size_t message_size, size_t ring_buffer_size)
Create a message set.
Definition: message.c:127
int fr_message_done(fr_message_t *m)
Mark a message as done.
Definition: message.c:190
fr_message_t * fr_message_reserve(fr_message_set_t *ms, size_t reserve_size)
Reserve a message.
Definition: message.c:934
int fr_message_set_messages_used(fr_message_set_t *ms)
Count the number of used messages.
Definition: message.c:1212
void fr_message_set_debug(fr_message_set_t *ms, FILE *fp)
Print debug information about the message set.
Definition: message.c:1262
void fr_message_set_gc(fr_message_set_t *ms)
Garbage collect the message set.
Definition: message.c:1238
fr_message_t * fr_message_alloc(fr_message_set_t *ms, fr_message_t *m, size_t actual_packet_size)
Allocate packet data for a message.
Definition: message.c:988
A Message set, composed of message headers and ring buffer data.
Definition: message.c:95
size_t rb_size
cache-aligned size in the ring buffer
Definition: message.h:51
fr_time_t when
when this message was sent
Definition: message.h:47
uint8_t * data
pointer to the data in the ring buffer
Definition: message.h:49
size_t data_size
size of the data in the ring buffer
Definition: message.h:50
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition: nbo.h:137
static TALLOC_CTX * autofree
Definition: radclient-ng.c:104
static int max_control_plane
Definition: radius1_test.c:69
uint8_t vector[16]
Definition: radius1_test.c:61
int main(int argc, char *argv[])
Definition: radius1_test.c:521
#define MAX_KEVENTS
Definition: radius1_test.c:46
#define MAX_MESSAGES
Definition: radius1_test.c:44
static rlm_rcode_t test_process(UNUSED void const *instance, request_t *request, fr_io_action_t action)
Definition: radius1_test.c:92
static fr_schedule_worker_t workers[MAX_WORKERS]
Definition: radius1_test.c:77
static int test_decode(UNUSED void const *instance, request_t *request, uint8_t *const data, size_t data_len)
Definition: radius1_test.c:99
static ssize_t test_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
Definition: radius1_test.c:114
struct sockaddr_storage src
Definition: radius1_test.c:64
static size_t test_nak(void const *instance, UNUSED void *packet_ctx, uint8_t *const packet, size_t packet_len, UNUSED uint8_t *reply, UNUSED size_t reply_len)
Definition: radius1_test.c:139
#define MAX_CONTROL_PLANE
Definition: radius1_test.c:45
#define MAX_WORKERS
Definition: radius1_test.c:47
static char const * secret
Definition: radius1_test.c:75
socklen_t salen
Definition: radius1_test.c:65
#define MPRINT2
Definition: radius1_test.c:50
#define MPRINT1
Definition: radius1_test.c:49
static uint16_t my_port
Definition: radius1_test.c:74
static void master_process(TALLOC_CTX *ctx)
Definition: radius1_test.c:207
static fr_ipaddr_t my_ipaddr
Definition: radius1_test.c:73
static void * worker_thread(void *arg)
Definition: radius1_test.c:154
static void sig_ignore(int sig)
Definition: radius1_test.c:516
static bool quiet
Definition: radius1_test.c:71
static fr_app_io_t app_io
Definition: radius1_test.c:146
static int num_workers
Definition: radius1_test.c:70
static NEVER_RETURNS void usage(void)
Definition: radius1_test.c:79
static void send_reply(int sockfd, fr_channel_data_t *reply)
Definition: radius1_test.c:190
static int debug_lvl
Definition: radius1_test.c:68
static fr_event_list_t * events
Definition: radsniff.c:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
Signals that can be sent to a request.
int fr_socket_server_udp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
Open an IPv4/IPv6 unconnected UDP socket.
Definition: socket.c:867
int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface.
Definition: socket.c:229
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
#define talloc_get_type_abort_const
Definition: talloc.h:270
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition: talloc.h:51
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition: talloc.h:112
int fr_time_start(void)
Initialize the local time.
Definition: time.c:150
#define NSEC
Definition: time.h:377
"server local" time.
Definition: time.h:69
close(uq->fd)
static fr_event_list_t * el
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition: strerror.c:733
static fr_slen_t data
Definition: value.h:1259
fr_channel_t * fr_worker_channel_create(fr_worker_t *worker, TALLOC_CTX *ctx, fr_control_t *master)
Create a channel to the worker.
Definition: worker.c:1602
fr_worker_t * fr_worker_create(TALLOC_CTX *ctx, fr_event_list_t *el, char const *name, fr_log_t const *logger, fr_log_lvl_t lvl, fr_worker_config_t *config)
Create a worker.
Definition: worker.c:1353
void fr_worker(fr_worker_t *worker)
The main loop and entry point of the stand-alone worker thread.
Definition: worker.c:1490
A worker which takes packets from a master, and processes them.
Definition: worker.c:94
int id
ID of the worker 0..N.
Definition: radius1_test.c:54
fr_channel_t * ch
channel for communicating with the worker
Definition: radius1_test.c:57
pthread_t pthread_id
the thread of this worker
Definition: schedule.c:86
fr_worker_t * worker
the worker data structure
Definition: schedule.c:97
Scheduler specific information for worker threads.
Definition: schedule.c:83