All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
proto_bfd.c
Go to the documentation of this file.
1 /*
2  * proto_bfd.c BFD processing.
3  *
4  * Version: $Id: 4fd1b6f78fb73af3876e823814f7483408f98a68 $
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 (C) 2012 Network RADIUS SARL <info@networkradius.com>
21  */
22 
23 #include <freeradius-devel/radiusd.h>
24 #include <freeradius-devel/protocol.h>
25 #include <freeradius-devel/modules.h>
26 #include <freeradius-devel/rad_assert.h>
27 #include <freeradius-devel/event.h>
28 #include <freeradius-devel/md5.h>
29 #include <freeradius-devel/sha1.h>
30 
31 #define USEC (1000000)
32 #define BFD_MAX_SECRET_LENGTH 20
33 
34 typedef enum bfd_session_state_t {
40 
41 typedef enum bfd_diag_t {
51 } bfd_diag_t;
52 
53 typedef enum bfd_auth_type_t {
61 
62 #define BFD_AUTH_INVALID (BFD_AUTH_MET_KEYED_SHA1 + 1)
63 
64 typedef struct bfd_state_t {
65  int number;
66  int sockfd;
67 
69  const char *server;
70 
71 #ifdef HAVE_PTHREAD_H
72  bool blocked;
73  int pipefd[2];
74  pthread_t pthread_id;
75 #endif
76 
79  size_t secret_len;
80 
83  uint16_t local_port;
84  uint16_t remote_port;
85 
86  /*
87  * To simplify sending the packets.
88  */
89  struct sockaddr_storage remote_sockaddr;
90  socklen_t salen;
91 
94  struct timeval last_recv;
95  struct timeval next_recv;
96  struct timeval last_sent;
97 
100 
101  uint32_t local_disc;
102  uint32_t remote_disc;
103 
105 
106  uint32_t desired_min_tx_interval; /* in usec */
110 
112 
115 
117 
118  uint32_t recv_auth_seq;
119  uint32_t xmit_auth_seq;
120 
122 
125 
126  uint32_t detection_time;
128 
129  int passive;
130 } bfd_state_t;
131 
132 typedef struct bfd_auth_basic_t {
133  uint8_t auth_type;
134  uint8_t auth_len;
135  uint8_t key_id;
137 
138 
139 typedef struct bfd_auth_simple_t {
140  uint8_t auth_type;
141  uint8_t auth_len;
142  uint8_t key_id;
143  uint8_t password[16];
145 
146 typedef struct bfd_auth_md5_t {
147  uint8_t auth_type;
148  uint8_t auth_len;
149  uint8_t key_id;
150  uint8_t reserved;
151  uint32_t sequence_no;
154 
155 typedef struct bfd_auth_sha1_t {
156  uint8_t auth_type;
157  uint8_t auth_len;
158  uint8_t key_id;
159  uint8_t reserved;
160  uint32_t sequence_no;
163 
164 typedef union bfd_auth_t {
169 } bfd_auth_t;
170 
171 
172 /*
173  * A packet
174  */
175 typedef struct bfd_packet_t {
176 #ifdef WORDS_BIGENDIAN
177  unsigned int version : 3;
178  unsigned int diag : 5;
179  unsigned int state : 2;
180  unsigned int poll : 1;
181  unsigned int final : 1;
182  unsigned int control_plane_independent : 1;
183  unsigned int auth_present : 1;
184  unsigned int demand : 1;
185  unsigned int multipoint : 1;
186 #else
187  unsigned int diag : 5;
188  unsigned int version : 3;
189 
190  unsigned int multipoint : 1;
191  unsigned int demand : 1;
192  unsigned int auth_present : 1;
193  unsigned int control_plane_independent : 1;
194  unsigned int final : 1;
195  unsigned int poll : 1;
196  unsigned int state : 2;
197 #endif
198  uint8_t detect_multi;
199  uint8_t length;
200  uint32_t my_disc;
201  uint32_t your_disc;
209 typedef struct bfd_socket_t {
210  fr_ipaddr_t my_ipaddr;
211  uint16_t my_port;
212 
213  char const *interface;
214 
215  int number;
216  const char *server;
217 
218  uint32_t min_tx_interval;
219  uint32_t min_rx_interval;
220  uint32_t max_timeouts;
221  bool demand;
222 
223  bfd_auth_type_t auth_type;
224  uint8_t secret[BFD_MAX_SECRET_LENGTH];
225  size_t secret_len;
226 
227  rbtree_t *session_tree;
229 
230 static int bfd_start_packets(bfd_state_t *session);
231 static int bfd_start_control(bfd_state_t *session);
232 static int bfd_stop_control(bfd_state_t *session);
233 static void bfd_detection_timeout(void *ctx, struct timeval *now);
234 static int bfd_process(bfd_state_t *session, bfd_packet_t *bfd);
235 
236 static fr_event_list_t *el = NULL; /* don't ask */
237 
238 void bfd_init(fr_event_list_t *xel);
239 
241 {
242  el = xel;
243 }
244 
245 
246 #ifdef HAVE_PTHREAD_H
247 static void bfd_pthread_free(bfd_state_t *session)
248 {
249  session->blocked = true;
250 
251  close(session->pipefd[0]);
252  close(session->pipefd[1]);
253 
254  talloc_free(session->el);
255 
256  session->el = NULL;
257  session->pipefd[0] = session->pipefd[1] = -1;
258 
259  session->blocked = false;
260 }
261 
262 /*
263  * A child thread reads the packet from a pipe, and processes it.
264  */
265 static void bfd_pipe_recv(UNUSED fr_event_list_t *xel, int fd, void *ctx)
266 {
267  ssize_t num;
268  bfd_state_t *session = ctx;
269  bfd_packet_t bfd;
270 
271  if (session->blocked) return;
272 
273  /*
274  * Read the header
275  */
276  num = read(fd, &bfd, 4);
277  if ((num < 4) || (bfd.length < 4)) {
278  fail:
279  ERROR("BFD Failed reading from pipe!");
280  session->blocked = true;
281  return;
282  }
283 
284  /*
285  * Read the rest of the packet.
286  */
287  num = read(fd, ((uint8_t *) &bfd) + 4, bfd.length - 4);
288  if ((num < 0) || ((num + 4) != bfd.length)) goto fail;
289 
290  bfd_process(session, &bfd);
291 }
292 
293 /*
294  * Do nothing more than read from the sockets and process the
295  * timers.
296  */
297 static void *bfd_child_thread(void *ctx)
298 {
299  bfd_state_t *session = ctx;
300 
301  DEBUG("BFD %d starting child thread", session->number);
302  bfd_start_control(session);
303 
304  fr_event_loop(session->el);
305 
306  bfd_pthread_free(session);
307 
308  return NULL;
309 }
310 
311 
312 static int bfd_pthread_create(bfd_state_t *session)
313 {
314  int rcode;
315  pthread_attr_t attr;
316 
317  if (pipe(session->pipefd) < 0) {
318  ERROR("Failed opening pipe: %s", fr_syserror(errno));
319  return 0;
320  }
321 
322  session->el = fr_event_list_create(session, NULL);
323  if (!session->el) {
324  ERROR("Failed creating event list");
325  close_pipes:
326  close(session->pipefd[0]);
327  close(session->pipefd[1]);
328  session->pipefd[0] = session->pipefd[1] = -1;
329  return 0;
330  }
331 
332 #ifdef O_NONBLOCK
333  fcntl(session->pipefd[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC);
334  fcntl(session->pipefd[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC);
335 #endif
336 
337  if (!fr_event_fd_insert(session->el, 0, session->pipefd[0],
338  bfd_pipe_recv, session)) {
339  ERROR("Failed inserting file descriptor into event list: %s", fr_strerror());
340  goto close_pipes;
341  }
342 
343  pthread_attr_init(&attr);
344  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
345 
346  /*
347  * Create the thread detached, so that it cleans up it's
348  * own memory when it exits.
349  *
350  * Note that the function returns non-zero on error, NOT
351  * -1. The return code is the error, and errno isn't set.
352  */
353  rcode = pthread_create(&session->pthread_id, &attr,
354  bfd_child_thread, session);
355  if (rcode != 0) {
356  talloc_free(session->el);
357  session->el = NULL;
358  ERROR("Thread create failed: %s", fr_syserror(rcode));
359  goto close_pipes;
360  }
361  pthread_attr_destroy(&attr);
362 
363  return 1;
364 }
365 #endif /* HAVE_PTHREAD_H */
366 
367 
368 static const char *bfd_state[] = {
369  "admin-down",
370  "down",
371  "init",
372  "up"
373 };
374 
375 
376 static void bfd_request(bfd_state_t *session, REQUEST *request,
377  RADIUS_PACKET *packet)
378 {
379  memset(request, 0, sizeof(*request));
380  memset(packet, 0, sizeof(*packet));
381 
382  request->packet = packet;
383  request->server = session->server;
384  packet->src_ipaddr = session->local_ipaddr;
385  packet->src_port = session->local_port;
386  packet->dst_ipaddr = session->remote_ipaddr;
387  packet->dst_port = session->remote_port;
388  /* request->heap_offset = -1; */
389 }
390 
391 
392 static void bfd_trigger(bfd_state_t *session)
393 {
394  RADIUS_PACKET packet;
395  REQUEST request;
396  char buffer[256];
397 
398  snprintf(buffer, sizeof(buffer), "server.bfd.%s",
399  bfd_state[session->session_state]);
400 
401  bfd_request(session, &request, &packet);
402 
403  exec_trigger(&request, NULL, buffer, false);
404 }
405 
406 
407 static void bfd_session_free(void *ctx)
408 {
409  bfd_state_t *session = ctx;
410 
411 #ifdef WITH_PTHREAD_H
412  if (el != session->el) {
413  /*
414  * FIXME: this isn't particularly safe.
415  */
416  bfd_pthread_free(session);
417  }
418 #endif
419 
420  talloc_free(session);
421 }
422 
423 
425 {
426  int rcode;
427  size_t len;
428  char const *value = NULL;
429 
430  rcode = cf_pair_parse(cs, "secret", FR_ITEM_POINTER(PW_TYPE_STRING, &value), NULL, T_INVALID);
431  if (rcode != 0) return 0;
432 
433  len = strlen(value);
434 
435  if ((value[0] == '0') && (value[1] == 'x')) {
436  if (len > 42) {
437  cf_log_err(cf_section_to_item(cs), "Secret is too long");
438  return -1;
439  }
440 
441  if ((len & 0x01) != 0) {
442  cf_log_err(cf_section_to_item(cs), "Invalid hex length");
443  return -1;
444  }
445 
446  return fr_hex2bin(secret, BFD_MAX_SECRET_LENGTH, value + 2, (len - 2));
447  }
448 
449  if (len >= 20) {
450  cf_log_err(cf_section_to_item(cs), "Secret is too long");
451  return -1;
452  }
453 
454  memset(secret, 0, BFD_MAX_SECRET_LENGTH);
455  memcpy(secret, value, len);
456  return len;
457 }
458 
459 
460 
461 /*
462  * Create a new session.
463  */
465  CONF_SECTION *cs,
466  const fr_ipaddr_t *ipaddr, uint16_t port)
467 {
468  int rcode;
469  bool flag;
470  uint32_t number;
471  bfd_state_t *session;
472 
473  session = talloc_zero(sock, bfd_state_t);
474 
475  /*
476  * Initialize according to RFC.
477  */
478  session->number = sock->number++;
479  session->sockfd = sockfd;
480  session->session_state = BFD_STATE_DOWN;
481  session->server = sock->server;
482  session->local_disc = fr_rand();
483  session->remote_disc = 0;
484  session->local_diag = BFD_DIAG_NONE;
485  session->desired_min_tx_interval = sock->min_tx_interval * 1000;
486  session->required_min_rx_interval = sock->min_rx_interval * 1000;
487  session->remote_min_rx_interval = 1;
488  session->demand_mode = sock->demand;
489  session->remote_demand_mode = false;
490  session->detect_multi = sock->max_timeouts;
491  session->auth_type = BFD_AUTH_RESERVED;
492  session->recv_auth_seq = 0;
493  session->xmit_auth_seq = fr_rand();
494  session->auth_seq_known = 0;
495 
496  /*
497  * Allow over-riding of variables per session.
498  */
499  rcode = cf_pair_parse(cs, "demand", FR_ITEM_POINTER(PW_TYPE_BOOLEAN, &flag), NULL, T_INVALID);
500  if (rcode == 0) {
501  session->demand_mode = flag;
502  }
503 
504  rcode = cf_pair_parse(cs, "min_transmit_interval", FR_ITEM_POINTER(PW_TYPE_INTEGER, &number), NULL, T_INVALID);
505  if (rcode == 0) {
506  if (number < 100) number = 100;
507  if (number > 10000) number = 10000;
508 
509  session->desired_min_tx_interval = number * 1000;
510  }
511  rcode = cf_pair_parse(cs, "min_receive_interval", FR_ITEM_POINTER(PW_TYPE_INTEGER, &number), NULL, T_INVALID);
512  if (rcode == 0) {
513  if (number < 100) number = 100;
514  if (number > 10000) number = 10000;
515 
516  session->required_min_rx_interval = number * 1000;
517  }
518  rcode = cf_pair_parse(cs, "max_timeouts", FR_ITEM_POINTER(PW_TYPE_INTEGER, &number), NULL, T_INVALID);
519  if (rcode == 0) {
520  if (number == 0) number = 1;
521  if (number > 10) number = 10;
522 
523  session->detect_multi = number;
524  }
525 
526  session->auth_type = sock->auth_type;
527 
528  /*
529  * Parse / over-ride the secrets.
530  */
531  session->secret_len = bfd_parse_secret(cs, session->secret);
532  if ((session->secret_len == 0) &&
533  (session->auth_type != BFD_AUTH_RESERVED)) {
534  if (sock->secret_len == 0) {
535  cf_log_err(cf_section_to_item(cs), "auth_type requires a secret");
536  talloc_free(session);
537  return NULL;
538  }
539 
540  session->secret_len = sock->secret_len;
541  memcpy(session->secret, sock->secret, sizeof(session->secret));
542  }
543 
544  /*
545  * Initialize the detection time.
546  */
547  if (!session->demand_mode) {
548  session->detection_time = session->required_min_rx_interval;
549  } else {
550  session->detection_time = session->desired_min_tx_interval;
551  }
552  session->detection_time *= session->detect_multi;
553 
554  /*
555  * And finally remember the session.
556  */
557  session->remote_ipaddr = *ipaddr;
558  session->remote_port = port;
559 
560  session->local_ipaddr = sock->my_ipaddr;
561  session->local_port = sock->my_port;
562 
563  fr_ipaddr_to_sockaddr(ipaddr, port,
564  &session->remote_sockaddr, &session->salen);
565 
566  if (!rbtree_insert(sock->session_tree, session)) {
567  ERROR("FAILED creating new session!");
568  talloc_free(session);
569  return NULL;
570  }
571 
572  bfd_trigger(session);
573 
574  /*
575  * Check for threaded / non-threaded operation.
576  */
577  if (el) {
578  session->el = el;
579 
580  bfd_start_control(session);
581 
582 #ifdef HAVE_PTHREAD_H
583  session->pipefd[0] = session->pipefd[1] = -1;
584  session->pthread_id = pthread_self();
585  } else {
586  if (!bfd_pthread_create(session)) {
587  rbtree_deletebydata(sock->session_tree, session);
588  talloc_free(session);
589  return NULL;
590  }
591 #endif
592  }
593 
594  return session;
595 }
596 
597 
598 static int bfd_verify_sequence(bfd_state_t *session, uint32_t sequence_no,
599  int keyed)
600 {
601  uint32_t start, stop;
602 
603  start = session->recv_auth_seq;
604  if (keyed) {
605  start++;
606  }
607  stop = start + 3 * session->detect_multi;
608 
609  if (start < stop) {
610  if ((sequence_no < start) ||
611  (sequence_no > stop)) {
612  return 0;
613  }
614 
615  } else { /* start is ~2^32, stop is ~10 */
616  if ((sequence_no > start) &&
617  (sequence_no < stop)) {
618  return 0;
619  }
620  }
621 
622  return 1;
623 }
624 
625 static void bfd_calc_md5(bfd_state_t *session, bfd_packet_t *bfd)
626 {
627  FR_MD5_CTX ctx;
628  bfd_auth_md5_t *md5 = &bfd->auth.md5;
629 
630  rad_assert(session->secret_len <= sizeof(md5->digest));
631  rad_assert(md5->auth_len == sizeof(*md5));
632 
633  memset(md5->digest, 0, sizeof(md5->digest));
634  memcpy(md5->digest, session->secret, session->secret_len);
635 
636  fr_md5_init(&ctx);
637  fr_md5_update(&ctx, (const uint8_t *) bfd, bfd->length);
638  fr_md5_final(md5->digest, &ctx);
639 }
640 
641 static void bfd_auth_md5(bfd_state_t *session, bfd_packet_t *bfd)
642 {
643  bfd_auth_md5_t *md5 = &bfd->auth.md5;
644 
645  md5->auth_type = session->auth_type;
646  md5->auth_len = sizeof(*md5);
647  bfd->length += md5->auth_len;
648 
649  md5->key_id = 0;
650  md5->sequence_no = session->xmit_auth_seq++;
651 
652  bfd_calc_md5(session, bfd);
653 }
654 
655 static int bfd_verify_md5(bfd_state_t *session, bfd_packet_t *bfd)
656 {
657  int rcode;
658  bfd_auth_md5_t *md5 = &bfd->auth.md5;
659  uint8_t digest[sizeof(md5->digest)];
660 
661  if (md5->auth_len != sizeof(*md5)) return 0;
662 
663  if (md5->key_id != 0) return 0;
664 
665  memcpy(digest, md5->digest, sizeof(digest));
666 
667  bfd_calc_md5(session, bfd);
668  rcode = fr_radius_digest_cmp(digest, md5->digest, sizeof(digest));
669 
670  memcpy(md5->digest, digest, sizeof(md5->digest)); /* pedantic */
671 
672  if (rcode != 0) {
673  DEBUG("BFD %d MD5 Digest failed: **** RE-ENTER THE SECRET ON BOTH ENDS ****", session->number);
674  return 0;
675  }
676 
677  /*
678  * Do this AFTER the authentication instead of before!
679  */
680  if (!session->auth_seq_known) {
681  session->auth_seq_known = 1;
682 
683  } else if (!bfd_verify_sequence(session, md5->sequence_no,
684  (md5->auth_type == BFD_AUTH_MET_KEYED_MD5))) {
685  DEBUG("MD5 sequence out of window");
686  return 0;
687  }
688 
689  session->recv_auth_seq = md5->sequence_no;
690 
691  return 1;
692 }
693 
694 static void bfd_calc_sha1(bfd_state_t *session, bfd_packet_t *bfd)
695 {
696  fr_sha1_ctx ctx;
697  bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
698 
699  rad_assert(session->secret_len <= sizeof(sha1->digest));
700  rad_assert(sha1->auth_len == sizeof(*sha1));
701 
702  memset(sha1->digest, 0, sizeof(sha1->digest));
703  memcpy(sha1->digest, session->secret, session->secret_len);
704 
705  fr_sha1_init(&ctx);
706  fr_sha1_update(&ctx, (const uint8_t *) bfd, bfd->length);
707  fr_sha1_final(sha1->digest, &ctx);
708 }
709 
710 static void bfd_auth_sha1(bfd_state_t *session, bfd_packet_t *bfd)
711 {
712  bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
713 
714  sha1->auth_type = session->auth_type;
715  sha1->auth_len = sizeof(*sha1);
716  bfd->length += sha1->auth_len;
717 
718  sha1->key_id = 0;
719  sha1->sequence_no = session->xmit_auth_seq++;
720 
721  bfd_calc_sha1(session, bfd);
722 }
723 
724 static int bfd_verify_sha1(bfd_state_t *session, bfd_packet_t *bfd)
725 {
726  int rcode;
727  bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
728  uint8_t digest[sizeof(sha1->digest)];
729 
730  if (sha1->auth_len != sizeof(*sha1)) return 0;
731 
732  if (sha1->key_id != 0) return 0;
733 
734  memcpy(digest, sha1->digest, sizeof(digest));
735 
736  bfd_calc_sha1(session, bfd);
737  rcode = fr_radius_digest_cmp(digest, sha1->digest, sizeof(digest));
738 
739  memcpy(sha1->digest, digest, sizeof(sha1->digest)); /* pedantic */
740 
741  if (rcode != 0) {
742  DEBUG("BFD %d SHA1 Digest failed: **** RE-ENTER THE SECRET ON BOTH ENDS ****", session->number);
743  return 0;
744  }
745 
746  /*
747  * Do this AFTER the authentication instead of before!
748  */
749  if (!session->auth_seq_known) {
750  session->auth_seq_known = 1;
751 
752  } else if (!bfd_verify_sequence(session, sha1->sequence_no,
753  (sha1->auth_type == BFD_AUTH_MET_KEYED_SHA1))) {
754  DEBUG("SHA1 sequence out of window");
755  return 0;
756  }
757 
758  session->recv_auth_seq = sha1->sequence_no;
759 
760  return 1;
761 }
762 
763 
764 static int bfd_authenticate(bfd_state_t *session, bfd_packet_t *bfd)
765 {
766  switch (bfd->auth.basic.auth_type) {
767  case BFD_AUTH_RESERVED:
768  return 0;
769 
770  case BFD_AUTH_SIMPLE:
771  break;
772 
773  case BFD_AUTH_KEYED_MD5:
775  return bfd_verify_md5(session, bfd);
776 
777  case BFD_AUTH_KEYED_SHA1:
779  return bfd_verify_sha1(session, bfd);
780  }
781 
782  return 0;
783 }
784 
786  bfd_packet_t *bfd)
787 {
788  memset(bfd, 0, sizeof(*bfd));
789 
790  bfd->version = 1;
791  bfd->diag = session->local_diag;
792  bfd->state = session->session_state;
793  bfd->poll = 0; /* fixed by poll response */
794  bfd->final = 0; /* fixed by poll response */
795  bfd->control_plane_independent = 0;
796 
797  if (session->auth_type == BFD_AUTH_RESERVED) {
798  bfd->auth_present = 0;
799  } else {
800  bfd->auth_present = 1;
801  }
802 
803  /*
804  * If we're UP / UP, signal that we've entered demand
805  * mode, and stop sending packets.
806  */
807  if (session->demand_mode &&
808  (session->session_state == BFD_STATE_UP) &&
809  (session->remote_session_state == BFD_STATE_UP)) {
810  bfd->demand = true;
811 
812  DEBUG("BFD %d demand mode UP / UP, sending ACK and done.",
813  session->number);
814  bfd_stop_control(session);
815  } else {
816  bfd->demand = false;
817  }
818 
819  bfd->multipoint = 0;
820  bfd->detect_multi = session->detect_multi;
821  bfd->length = 24; /* auth types add to this later */
822 
823  bfd->my_disc = session->local_disc;
824  bfd->your_disc = session->remote_disc;
825 
828 
830 }
831 
832 
833 static void bfd_sign(bfd_state_t *session, bfd_packet_t *bfd)
834 {
835  if (bfd->auth_present) {
836  switch (session->auth_type) {
837  case BFD_AUTH_RESERVED:
838  break;
839 
840  case BFD_AUTH_SIMPLE:
841  break;
842 
843  case BFD_AUTH_KEYED_MD5:
845  bfd_auth_md5(session, bfd);
846  break;
847 
848  case BFD_AUTH_KEYED_SHA1:
850  bfd_auth_sha1(session, bfd);
851  break;
852  }
853  }
854 }
855 
856 
857 /*
858  * Send a packet.
859  */
860 static void bfd_send_packet(void *ctx, UNUSED struct timeval *now)
861 {
862  bfd_state_t *session = ctx;
863  bfd_packet_t bfd;
864 
865  bfd_control_packet_init(session, &bfd);
866 
867  if (session->doing_poll) {
868  bfd.poll = 1;
869  }
870 
871  if (!bfd.demand) {
872  bfd_start_packets(session);
873  }
874 
875  bfd_sign(session, &bfd);
876 
877  DEBUG("BFD %d sending packet state %s",
878  session->number, bfd_state[session->session_state]);
879  if (sendto(session->sockfd, &bfd, bfd.length, 0,
880  (struct sockaddr *) &session->remote_sockaddr,
881  session->salen) < 0) {
882  ERROR("Failed sending packet: %s", fr_syserror(errno));
883  }
884 }
885 
886 static int bfd_start_packets(bfd_state_t *session)
887 {
888  uint32_t interval, base;
889  uint64_t jitter;
890  struct timeval now;
891 
892  /*
893  * Reset the timers.
894  */
895  fr_event_delete(session->el, &session->ev_packet);
896 
897  gettimeofday(&session->last_sent, NULL);
898  now = session->last_sent;
899 
900  if (session->desired_min_tx_interval >= session->remote_min_rx_interval) {
901  interval = session->desired_min_tx_interval;
902  } else {
903  interval = session->remote_min_rx_interval;
904  }
905  base = (interval * 3) / 4;
906  jitter = fr_rand(); /* 32-bit number */
907 
908  if (session->detect_multi == 1) {
909  jitter *= 644245094; /* 15% of 2^32 */
910 
911  } else {
912  jitter *= (1 << 30); /* 25% of 2^32 */
913  }
914 
915  jitter >>= 32;
916  jitter *= interval;
917  jitter >>= 32;
918  interval = base;
919  interval += jitter;
920 
921  if (interval >= USEC) {
922  now.tv_sec += interval / USEC;
923  }
924  now.tv_usec += interval % USEC;
925  if (now.tv_usec >= USEC) {
926  now.tv_sec++;
927  now.tv_usec -= USEC;
928  }
929 
930  if (!fr_event_insert(session->el, bfd_send_packet, session, &now,
931  &session->ev_packet)) {
932  rad_assert("Failed to insert event" == NULL);
933  }
934 
935  return 0;
936 }
937 
938 
939 static void bfd_set_timeout(bfd_state_t *session, struct timeval *when)
940 {
941  struct timeval now = *when;
942 
943  fr_event_delete(session->el, &session->ev_timeout);
944 
945  if (session->detection_time >= USEC) {
946  now.tv_sec += session->detection_time / USEC;
947  }
948  now.tv_usec += session->detection_time % USEC;
949  if (now.tv_usec >= USEC) {
950  now.tv_sec++;
951  now.tv_usec -= USEC;
952  }
953 
954  if (session->detect_multi >= 2) {
955  uint32_t delay;
956 
957  session->next_recv = *when;
958  delay = session->detection_time / session->detect_multi;
959  delay += delay / 2;
960 
961  if (delay > USEC) {
962  session->next_recv.tv_sec += delay / USEC;
963  }
964  session->next_recv.tv_usec += delay % USEC;
965  if (session->next_recv.tv_usec >= USEC) {
966  session->next_recv.tv_sec++;
967  session->next_recv.tv_usec -= USEC;
968  }
969  }
970 
971  if (!fr_event_insert(session->el, bfd_detection_timeout, session, &now,
972  &session->ev_timeout)) {
973  rad_assert("Failed to insert event" == NULL);
974  }
975 }
976 
977 
978 static int bfd_start_control(bfd_state_t *session)
979 {
980  if (session->remote_min_rx_interval == 0) return 0;
981 
982  if ((session->remote_disc == 0) && session->passive) return 0;
983 
984  if (session->remote_demand_mode &&
985  (session->session_state == BFD_STATE_UP) &&
986  (session->remote_session_state == BFD_STATE_UP) &&
987  !session->doing_poll) {
988  DEBUG("BFD %d warning: asked to start UP / UP ?",
989  session->number);
990  rad_assert(0 == 1);
991  bfd_stop_control(session);
992  return 0;
993  }
994 
995  bfd_set_timeout(session, &session->last_recv);
996 
997  if (session->ev_packet) return 0;
998 
999  return bfd_start_packets(session);
1000 }
1001 
1002 static int bfd_stop_control(bfd_state_t *session)
1003 {
1004  fr_event_delete(session->el, &session->ev_timeout);
1005  fr_event_delete(session->el, &session->ev_packet);
1006  return 1;
1007 }
1008 
1009 
1010 static int bfd_start_poll(bfd_state_t *session)
1011 {
1012  if (session->doing_poll) return 0;
1013 
1014  /*
1015  * Already sending packets. Reset the timers and set the
1016  * poll bit.
1017  */
1018  if (!session->remote_demand_mode) {
1019  bfd_stop_control(session);
1020  }
1021 
1022  session->doing_poll = 1;
1023 
1024  /*
1025  * Send POLL packets, even if we're not sending CONTROL
1026  * packets.
1027  */
1028  return bfd_start_packets(session);
1029 }
1030 
1031 static int bfd_stop_poll(bfd_state_t *session)
1032 {
1033  if (!session->doing_poll) return 0;
1034 
1035  /*
1036  * We tried to increase the min_tx during a polling
1037  * sequence. That isn't kosher, so we instead waited
1038  * until now.
1039  */
1040  if (session->next_min_tx_interval) {
1041  session->desired_min_tx_interval = session->next_min_tx_interval;
1042  session->next_min_tx_interval = 0;
1043  }
1044 
1045  /*
1046  * Already sending packets. Clear the poll bit and
1047  * re-set the timers.
1048  */
1049  if (!session->remote_demand_mode) {
1050  rad_assert(session->ev_timeout != NULL);
1051  rad_assert(session->ev_packet != NULL);
1052  session->doing_poll = 0;
1053 
1054  bfd_stop_control(session);
1055  bfd_start_control(session);
1056  return 1;
1057  }
1058 
1059  session->doing_poll = 0;
1060 
1061  return bfd_stop_control(session);
1062 }
1063 
1065  uint32_t value)
1066 {
1067  /*
1068  * Increasing the value: don't change it if we're already
1069  * polling.
1070  */
1071  if (session->doing_poll &&
1072  (session->session_state == BFD_STATE_UP) &&
1073  (value > session->desired_min_tx_interval)) {
1074  session->next_min_tx_interval = value;
1075  return;
1076  }
1077 
1078  if (session->session_state != BFD_STATE_UP) {
1079  if (value < USEC) value = USEC;
1080  }
1081 
1082  session->desired_min_tx_interval = value;
1083  bfd_stop_control(session);
1084  session->doing_poll = 0;
1085 
1086  bfd_start_poll(session);
1087 }
1088 
1089 
1090 static void bfd_detection_timeout(void *ctx, struct timeval *now)
1091 {
1092  bfd_state_t *session = ctx;
1093 
1094  DEBUG("BFD %d Timeout state %s ****** ", session->number,
1095  bfd_state[session->session_state]);
1096 
1097  if (!session->demand_mode) {
1098  switch (session->session_state) {
1099  case BFD_STATE_INIT:
1100  case BFD_STATE_UP:
1101  goto start_poll;
1102 
1103  default:
1104  break;
1105  }
1106 
1107  } else if (!session->doing_poll) {
1108  start_poll:
1109  DEBUG("BFD %d State <timeout> -> DOWN (control expired)", session->number);
1110  session->session_state = BFD_STATE_DOWN;
1111  session->local_diag = BFD_CTRL_EXPIRED;
1112  bfd_trigger(session);
1113 
1115  }
1116 
1117  session->remote_disc = 0;
1118 
1119  if (session->detection_timeouts >= 2) {
1120  session->auth_seq_known = 0;
1121  }
1122 
1123  session->detection_timeouts++;
1124 
1125  bfd_set_timeout(session, now);
1126 }
1127 
1128 
1129 /*
1130  * Send an immediate response to a poll request.
1131  *
1132  * Note that this doesn't affect our "last_sent" timer.
1133  * That's set only when we intend to send a packet.
1134  */
1135 static void bfd_poll_response(bfd_state_t *session)
1136 {
1137  bfd_packet_t bfd;
1138 
1139  bfd_control_packet_init(session, &bfd);
1140  bfd.poll = 0; /* Section 6.5 */
1141  bfd.final = 1;
1142 
1143  /*
1144  * TO DO: rate limit poll responses.
1145  */
1146 
1147  bfd_sign(session, &bfd);
1148 
1149  if (sendto(session->sockfd, &bfd, bfd.length, 0,
1150  (struct sockaddr *) &session->remote_sockaddr,
1151  session->salen) < 0) {
1152  ERROR("Failed sending poll response: %s", fr_syserror(errno));
1153  }
1154 }
1155 
1156 
1157 static int bfd_process(bfd_state_t *session, bfd_packet_t *bfd)
1158 {
1159  if (bfd->auth_present &&
1160  (session->auth_type == BFD_AUTH_RESERVED)) {
1161  DEBUG("BFD %d packet asked to authenticate an unauthenticated session.", session->number);
1162  return 0;
1163  }
1164 
1165  if (!bfd->auth_present &&
1166  (session->auth_type != BFD_AUTH_RESERVED)) {
1167  DEBUG("BFD %d packet failed to authenticate an authenticated session.", session->number);
1168  return 0;
1169  }
1170 
1171  if (bfd->auth_present && !bfd_authenticate(session, bfd)) {
1172  return 0;
1173  }
1174 
1175  DEBUG("BFD %d processing packet", session->number);
1176  session->remote_disc = bfd->my_disc;
1177  session->remote_session_state = bfd->state;
1178  session->remote_demand_mode = bfd->demand;
1179 
1180  /*
1181  * The other end is reducing the RX interval. Do that
1182  * now.
1183  */
1184  if ((bfd->required_min_rx_interval < session->remote_min_rx_interval) &&
1185  !session->demand_mode) {
1186  bfd_stop_control(session);
1187  bfd_start_control(session);
1188  }
1190 
1192  if (bfd->min_echo_rx_interval == 0) {
1193 #if 0
1194  /*
1195  * Echo packets are BFD packets with
1196  * application-layer data echoed back to the
1197  * sender. We don't do that.
1198  */
1199  bfd_stop_echo(session);
1200 #endif
1201  }
1202 
1203  if (session->doing_poll && bfd->final) {
1204  bfd_stop_poll(session);
1205  }
1206 
1207  /*
1208  * Update transmit intervals as in 6.8.7
1209  */
1210 
1211  /*
1212  * Update detection times as in 6.8.4
1213  */
1214  if (!session->demand_mode) {
1215  if (session->required_min_rx_interval >= bfd->desired_min_tx_interval) {
1216  session->detection_time = session->required_min_rx_interval;
1217  } else {
1218  session->detection_time = bfd->desired_min_tx_interval;
1219  }
1220  } else {
1221  if (session->desired_min_tx_interval >= session->remote_min_rx_interval) {
1222  session->detection_time = session->desired_min_tx_interval;
1223  } else {
1224  session->detection_time = session->remote_min_rx_interval;
1225  }
1226  }
1227  session->detection_time *= session->detect_multi;
1228 
1229  if (session->session_state == BFD_STATE_ADMIN_DOWN) {
1230  DEBUG("Discarding BFD packet (admin down)");
1231  return 0;
1232  }
1233 
1234  if (bfd->state == BFD_STATE_ADMIN_DOWN) {
1235  if (bfd->state != BFD_STATE_DOWN) {
1236  session->local_diag = BFD_NEIGHBOR_DOWN;
1237  }
1238 
1239  DEBUG("BFD %d State %s -> DOWN (admin down)",
1240  session->number, bfd_state[session->session_state]);
1241  session->session_state = BFD_STATE_DOWN;
1242  bfd_trigger(session);
1243 
1245 
1246  } else {
1247  switch (session->session_state) {
1248  case BFD_STATE_DOWN:
1249  switch (bfd->state) {
1250  case BFD_STATE_DOWN:
1251  DEBUG("BFD %d State DOWN -> INIT (neighbor down)",
1252  session->number);
1253  session->session_state = BFD_STATE_INIT;
1254  bfd_trigger(session);
1255 
1257  break;
1258 
1259  case BFD_STATE_INIT:
1260  DEBUG("BFD %d State DOWN -> UP (neighbor INIT)",
1261  session->number);
1262  session->session_state = BFD_STATE_UP;
1263  bfd_trigger(session);
1264  break;
1265 
1266  default: /* don't change anything */
1267  break;
1268  }
1269  break;
1270 
1271  case BFD_STATE_INIT:
1272  switch (bfd->state) {
1273  case BFD_STATE_INIT:
1274  case BFD_STATE_UP:
1275  DEBUG("BFD %d State INIT -> UP",
1276  session->number);
1277  session->session_state = BFD_STATE_UP;
1278  bfd_trigger(session);
1279  break;
1280 
1281  default: /* don't change anything */
1282  break;
1283  }
1284  break;
1285 
1286  case BFD_STATE_UP:
1287  switch (bfd->state) {
1288  case BFD_STATE_DOWN:
1289  session->local_diag = BFD_NEIGHBOR_DOWN;
1290 
1291  DEBUG("BFD %d State UP -> DOWN (neighbor down)",
1292  session->number);
1293  session->session_state = BFD_STATE_DOWN;
1294  bfd_trigger(session);
1295 
1297  break;
1298 
1299  default:
1300  break;
1301  }
1302  break;
1303 
1304  default:
1305  DEBUG("Internal sanity check failed");
1306  return 0;
1307  }
1308  }
1309 
1310  /*
1311  * Check if demand mode should be active (Section 6.6)
1312  */
1313  if (session->remote_demand_mode &&
1314  (session->session_state == BFD_STATE_UP) &&
1315  (session->remote_session_state == BFD_STATE_UP)) {
1316  DEBUG("BFD %d demand mode UP / UP, stopping packets",
1317  session->number);
1318  bfd_stop_control(session);
1319  }
1320 
1321  if (bfd->poll) {
1322  bfd_poll_response(session);
1323  }
1324 
1325  /*
1326  * We've received the packet for the purpose of Section
1327  * 6.8.4.
1328  */
1329  gettimeofday(&session->last_recv, NULL);
1330 
1331  /*
1332  * We've received a packet, but missed the previous one.
1333  * Warn about it.
1334  */
1335  if ((session->detect_multi >= 2) &&
1336  ((session->last_recv.tv_sec > session->next_recv.tv_sec) ||
1337  ((session->last_recv.tv_sec == session->next_recv.tv_sec) &&
1338  (session->last_recv.tv_usec > session->next_recv.tv_usec)))) {
1339  RADIUS_PACKET packet;
1340  REQUEST request;
1341 
1342  bfd_request(session, &request, &packet);
1343 
1344  exec_trigger(&request, NULL, "server.bfd.warn", false);
1345  }
1346 
1347 
1348  if ((!session->remote_demand_mode) ||
1349  (session->session_state != BFD_STATE_UP) ||
1350  (session->remote_session_state != BFD_STATE_UP)) {
1351  bfd_start_control(session);
1352  }
1353 
1354  if (session->server) {
1355  REQUEST *request;
1356  RADIUS_PACKET *packet, *reply;
1357 
1358  request = request_alloc(session);
1359  packet = fr_radius_alloc(request, 0);
1360  reply = fr_radius_alloc(request, 0);
1361 
1362  bfd_request(session, request, packet);
1363 
1364  memset(reply, 0, sizeof(*reply));
1365 
1366  request->reply = reply;
1367  request->reply->src_ipaddr = session->remote_ipaddr;
1368  request->reply->src_port = session->remote_port;
1369  request->reply->dst_ipaddr = session->local_ipaddr;
1370  request->reply->dst_port = session->local_port;
1371 
1372  /*
1373  * FIXME: add my state, remote state as VPs?
1374  */
1375 
1376  if (rad_debug_lvl) {
1377  request->log.lvl = RAD_REQUEST_LVL_DEBUG2;
1378  request->log.func = vradlog_request;
1379  }
1380  request->component = "";
1381  request->module = "";
1382 
1383  DEBUG2("server %s {", request->server);
1384  process_authorize(0, request);
1385  DEBUG("}");
1386 
1387  /*
1388  * FIXME: grab attributes from the reply
1389  * and cache them for use in the next request.
1390  */
1391  talloc_free(request);
1392  }
1393 
1394  return 1;
1395 }
1396 
1397 
1398 /*
1399  * Requirements of 6.8.3
1400  *
1401  * Changes to:
1402  *
1403  * session->desired_min_tx_interval
1404  * session->required_min_rx_interval
1405  *
1406  * mean we start polling.
1407  */
1408 
1409 /*
1410  * Check if an incoming request is "ok"
1411  *
1412  * It takes packets, not requests. It sees if the packet looks
1413  * OK. If so, it does a number of sanity checks on it.
1414  */
1415 static int bfd_socket_recv(rad_listen_t *listener)
1416 {
1417  ssize_t rcode;
1418  bfd_socket_t *sock = listener->data;
1419  bfd_state_t *session;
1420  bfd_state_t my_session;
1421  struct sockaddr_storage src;
1422  socklen_t sizeof_src = sizeof(src);
1423  bfd_packet_t bfd;
1424 
1425  rcode = recvfrom(listener->fd, &bfd, sizeof(bfd), 0,
1426  (struct sockaddr *)&src, &sizeof_src);
1427  if (rcode < 0) {
1428  ERROR("Failed receiving packet: %s", fr_syserror(errno));
1429  return 0;
1430  }
1431 
1432  if (rcode < 24) {
1433  DEBUG("BFD packet is too short (%d < 24)", (int) rcode);
1434  return 0;
1435  }
1436 
1437  if (bfd.version != 1) {
1438  DEBUG("BFD packet has wrong version (%d != 1)", bfd.version);
1439  return 0;
1440  }
1441 
1442  if (bfd.length < 24) {
1443  DEBUG("BFD packet has wrong length (%d < 24)", bfd.length);
1444  return 0;
1445  }
1446 
1447  if (bfd.auth_present) {
1448  if (bfd.length < 26) {
1449  DEBUG("BFD packet has wrong length (%d < 26)",
1450  bfd.length);
1451  return 0;
1452  }
1453 
1454  if (bfd.length < 24 + bfd.auth.basic.auth_len) {
1455  DEBUG("BFD packet is too short (%d < %d)",
1456  bfd.length, 24 + bfd.auth.basic.auth_len);
1457  return 0;
1458 
1459  }
1460 
1461  if (bfd.length != 24 + bfd.auth.basic.auth_len) {
1462  DEBUG("WARNING: What is the extra data?");
1463  }
1464 
1465  }
1466 
1467  if (bfd.detect_multi == 0) {
1468  DEBUG("BFD packet has detect_multi == 0");
1469  return 0;
1470  }
1471 
1472  if (bfd.multipoint != 0) {
1473  DEBUG("BFD packet has multi != 0");
1474  return 0;
1475  }
1476 
1477  if (bfd.my_disc == 0) {
1478  DEBUG("BFD packet has my_disc == 0");
1479  return 0;
1480  }
1481 
1482  if ((bfd.your_disc == 0) &&
1483  !((bfd.state == BFD_STATE_DOWN) ||
1484  (bfd.state == BFD_STATE_ADMIN_DOWN))) {
1485  DEBUG("BFD packet has invalid your-disc / state");
1486  return 0;
1487  }
1488 
1489  /*
1490  * We SHOULD use "your_disc", but what the heck.
1491  */
1492  fr_ipaddr_from_sockaddr(&src, sizeof_src,
1493  &my_session.remote_ipaddr,
1494  &my_session.remote_port);
1495 
1496  session = rbtree_finddata(sock->session_tree, &my_session);
1497  if (!session) {
1498  DEBUG("BFD unknown peer");
1499  return 0;
1500  }
1501 
1502 #ifdef HAVE_PTHREAD_H
1503  if (!el) {
1504  uint8_t *p = (uint8_t *) &bfd;
1505  size_t total = bfd.length;
1506 
1507  /*
1508  * A child has had a problem. Do some cleanups.
1509  */
1510  if (session->blocked) bfd_pthread_free(session);
1511 
1512  /*
1513  * No event list, try to create a new one.
1514  */
1515  if (!session->el && !bfd_pthread_create(session)) {
1516  DEBUG("BFD %d - error trying to create child thread",
1517  session->number);
1518  return 0;
1519  }
1520 
1521  do {
1522  rcode = write(session->pipefd[1], p, total);
1523  if ((rcode < 0) && (errno == EINTR)) continue;
1524 
1525  if (rcode < 0) {
1526  session->blocked = true;
1527  return 0;
1528  }
1529 
1530  total -= rcode;
1531  p += rcode;
1532  } while (total > 0);
1533  return 0;
1534  }
1535 #endif
1536 
1537  return bfd_process(session, &bfd);
1538 }
1539 
1540 static int bfd_parse_ip_port(CONF_SECTION *cs, fr_ipaddr_t *ipaddr, uint16_t *port)
1541 {
1542  int rcode;
1543 
1544  /*
1545  * Try IPv4 first
1546  */
1547  memset(ipaddr, 0, sizeof(*ipaddr));
1548  ipaddr->ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1549  rcode = cf_pair_parse(cs, "ipaddr", FR_ITEM_POINTER(PW_TYPE_IPV4_ADDR, ipaddr), NULL, T_INVALID);
1550  if (rcode < 0) return -1;
1551 
1552  if (rcode == 0) { /* successfully parsed IPv4 */
1553  ipaddr->af = AF_INET;
1554 
1555  } else { /* maybe IPv6? */
1556  rcode = cf_pair_parse(cs, "ipv6addr", FR_ITEM_POINTER(PW_TYPE_IPV6_ADDR, ipaddr), NULL, T_INVALID);
1557  if (rcode < 0) return -1;
1558 
1559  if (rcode == 1) {
1561  "No address specified in section");
1562  return -1;
1563  }
1564  ipaddr->af = AF_INET6;
1565  }
1566 
1567  rcode = cf_pair_parse(cs, "port", FR_ITEM_POINTER(PW_TYPE_SHORT, port), "0", T_INVALID);
1568  if (rcode < 0) return -1;
1569 
1570  return 0;
1571 }
1572 
1573 /*
1574  * @fixme: move some of this to parse
1575  */
1577 {
1578  CONF_ITEM *ci;
1579  CONF_SECTION *peer;
1580  uint16_t port;
1581  fr_ipaddr_t ipaddr;
1582 
1583  for (ci=cf_item_find_next(cs, NULL);
1584  ci != NULL;
1585  ci=cf_item_find_next(cs, ci)) {
1586  bfd_state_t *session, my_session;
1587 
1588  if (!cf_item_is_section(ci)) continue;
1589 
1590  peer = cf_item_to_section(ci);
1591 
1592  if (strcmp(cf_section_name1(peer), "peer") != 0) continue;
1593 
1594  if (bfd_parse_ip_port(peer, &ipaddr, &port) < 0) {
1595  return -1;
1596  }
1597 
1598  my_session.remote_ipaddr = ipaddr;
1599  my_session.remote_port = port;
1600  if (rbtree_finddata(sock->session_tree, &my_session) != NULL) {
1601  cf_log_err(ci, "Peers must have unique IP addresses");
1602  return -1;
1603  }
1604 
1605  session = bfd_new_session(sock, sockfd, peer, &ipaddr, port);
1606  if (!session) return -1;
1607  }
1608 
1609  return 0;
1610 }
1611 
1612 
1613 /*
1614  * None of these functions are used.
1615  */
1616 static int bfd_socket_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
1617 {
1618  rad_assert(0 == 1);
1619  return 0;
1620 }
1621 
1622 
1623 static int bfd_socket_encode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
1624 {
1625  rad_assert(0 == 1);
1626  return 0;
1627 }
1628 
1629 
1630 static int bfd_socket_decode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
1631 {
1632  rad_assert(0 == 1);
1633  return 0;
1634 }
1635 
1636 static int bfd_session_cmp(const void *one, const void *two)
1637 {
1638  const bfd_state_t *a = one;
1639  const bfd_state_t *b = two;
1640 
1641  return fr_ipaddr_cmp(&a->remote_ipaddr, &b->remote_ipaddr);
1642 }
1643 
1644 static void bfd_socket_free(rad_listen_t *this)
1645 {
1646  bfd_socket_t *sock = this->data;
1647 
1648  rbtree_free(sock->session_tree);
1649  talloc_free(sock);
1650  this->data = NULL;
1651 }
1652 
1653 static const FR_NAME_NUMBER auth_types[] = {
1654  { "none", BFD_AUTH_RESERVED },
1655  { "simple", BFD_AUTH_SIMPLE },
1656  { "keyed-md5", BFD_AUTH_KEYED_MD5 },
1657  { "met-keyed-md5", BFD_AUTH_MET_KEYED_MD5 },
1658  { "keyed-sha1", BFD_AUTH_KEYED_SHA1 },
1659  { "met-keyed-sha1", BFD_AUTH_MET_KEYED_SHA1 },
1660 
1661  { NULL, 0 }
1662 };
1663 
1664 
1666 {
1667  bfd_socket_t *sock = this->data;
1668  char const *auth_type_str = NULL;
1669  uint16_t listen_port;
1670  fr_ipaddr_t ipaddr;
1671 
1672  rad_assert(sock != NULL);
1673 
1674  if (bfd_parse_ip_port(cs, &ipaddr, &listen_port) < 0) {
1675  return -1;
1676  }
1677 
1678  sock->my_ipaddr = ipaddr;
1679  sock->my_port = listen_port;
1680 
1681  cf_pair_parse(cs, "interface", FR_ITEM_POINTER(PW_TYPE_STRING, &sock->interface), NULL, T_INVALID);
1682 
1683  cf_pair_parse(cs, "min_receive_interval", FR_ITEM_POINTER(PW_TYPE_INTEGER, &sock->min_rx_interval), "1000", T_BARE_WORD);
1684  cf_pair_parse(cs, "max_timeouts", FR_ITEM_POINTER(PW_TYPE_INTEGER, &sock->max_timeouts), "3", T_BARE_WORD);
1685  cf_pair_parse(cs, "demand", FR_ITEM_POINTER(PW_TYPE_BOOLEAN, &sock->demand), "no", T_DOUBLE_QUOTED_STRING);
1686  cf_pair_parse(cs, "auth_type", FR_ITEM_POINTER(PW_TYPE_STRING, &auth_type_str), NULL, T_INVALID);
1687 
1688  if (!this->server) {
1689  cf_pair_parse(cs, "server", FR_ITEM_POINTER(PW_TYPE_STRING, &sock->server), NULL, T_INVALID);
1690  } else {
1691  sock->server = this->server;
1692  }
1693 
1694  if (sock->min_tx_interval < 100) sock->min_tx_interval = 100;
1695  if (sock->min_tx_interval > 10000) sock->min_tx_interval = 10000;
1696 
1697  if (sock->min_rx_interval < 100) sock->min_rx_interval = 100;
1698  if (sock->min_rx_interval > 10000) sock->min_rx_interval = 10000;
1699 
1700  if (sock->max_timeouts == 0) sock->max_timeouts = 1;
1701  if (sock->max_timeouts > 10) sock->max_timeouts = 10;
1702 
1703  sock->auth_type = fr_str2int(auth_types, auth_type_str, BFD_AUTH_INVALID);
1704  if (sock->auth_type == BFD_AUTH_INVALID) {
1705  ERROR("Unknown auth_type '%s'", auth_type_str);
1706  exit(1);
1707  }
1708 
1709  if (sock->auth_type == BFD_AUTH_SIMPLE) {
1710  ERROR("'simple' authentication is insecure and is not supported");
1711  exit(1);
1712  }
1713 
1714  if (sock->auth_type != BFD_AUTH_RESERVED) {
1715  sock->secret_len = bfd_parse_secret(cs, sock->secret);
1716 
1717  if (sock->secret_len == 0) {
1718  ERROR("Cannot have empty secret");
1719  exit(1);
1720  }
1721 
1722  if (((sock->auth_type == BFD_AUTH_KEYED_MD5) ||
1723  (sock->auth_type == BFD_AUTH_MET_KEYED_MD5)) &&
1724  (sock->secret_len > 16)) {
1725  ERROR("Secret must be no more than 16 bytes when using MD5");
1726  exit(1);
1727  }
1728  }
1729 
1730  sock->session_tree = rbtree_create(sock, bfd_session_cmp, bfd_session_free, 0);
1731  if (!sock->session_tree) {
1732  ERROR("Failed creating session tree!");
1733  exit(1);
1734  }
1735 
1736  return 0;
1737 }
1738 
1740 {
1741  int rcode;
1742  int port;
1743  bfd_socket_t *sock = this->data;
1744 
1745  port = sock->my_port;
1746 
1747  this->fd = fr_socket_server_base(IPPROTO_UDP, &sock->my_ipaddr, &port, "bfd-control", true);
1748  if (this->fd < 0) {
1749  char buffer[256];
1750 
1751  this->print(this, buffer, sizeof(buffer));
1752 
1753  ERROR("Failed opening %s: %s", buffer, fr_syserror(errno));
1754  return -1;
1755  }
1756 
1757  rad_suid_up();
1758  rcode = fr_socket_server_bind(this->fd, &sock->my_ipaddr, &port, sock->interface);
1759  rad_suid_down();
1760  sock->my_port = port;
1761 
1762  if (rcode < 0) {
1763  char buffer[256];
1764  close(this->fd);
1765 
1766  this->print(this, buffer, sizeof(buffer));
1767  ERROR("Failed binding to %s: %s", buffer, fr_syserror(errno));
1768  return -1;
1769  }
1770 
1771  /*
1772  * Bootstrap the initial set of connections.
1773  */
1774  if (bfd_init_sessions(cs, sock, this->fd) < 0) {
1775  exit(1);
1776  }
1777 
1778  return 0;
1779 }
1780 
1781 static int bfd_socket_print(const rad_listen_t *this, char *buffer, size_t bufsize)
1782 {
1783  size_t len;
1784  bfd_socket_t *sock = this->data;
1785 
1786 #define FORWARD len = strlen(buffer); if (len >= (bufsize + 1)) return 0;buffer += len;bufsize -= len
1787 
1788  strlcpy(buffer, "bfd address ", bufsize);
1789  FORWARD;
1790 
1791  if ((sock->my_ipaddr.af == AF_INET) &&
1792  (sock->my_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
1793  strlcpy(buffer, "*", bufsize);
1794  } else {
1795  fr_inet_ntoh(&sock->my_ipaddr, buffer, bufsize);
1796  }
1797  FORWARD;
1798 
1799  strlcpy(buffer, " port ", bufsize);
1800  FORWARD;
1801 
1802  snprintf(buffer, bufsize, "%d", sock->my_port);
1803  FORWARD;
1804 
1805  return 1;
1806 }
1807 
1808 extern fr_protocol_t proto_bfd;
1809 fr_protocol_t proto_bfd = {
1811  .name = "bfd",
1812  .inst_size = sizeof(bfd_socket_t),
1813  .transports = TRANSPORT_UDP,
1814  .tls = false,
1815  .parse = bfd_socket_parse,
1816  .open = bfd_socket_open,
1817  .free = bfd_socket_free,
1818  .recv = bfd_socket_recv,
1819  .send = bfd_socket_send,
1820  .print = bfd_socket_print,
1821  .debug = common_packet_debug,
1822  .encode = bfd_socket_encode,
1823  .decode = bfd_socket_decode
1824 };
uint32_t my_disc
Definition: proto_bfd.c:200
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *data, size_t len)
Definition: sha1.c:106
void rad_suid_down(void)
Definition: util.c:1474
uint8_t key_id
Definition: proto_bfd.c:135
static ssize_t bfd_parse_secret(CONF_SECTION *cs, uint8_t secret[BFD_MAX_SECRET_LENGTH])
Definition: proto_bfd.c:424
int sockfd
Definition: proto_bfd.c:66
static int sockfd
Definition: radclient.c:59
uint8_t reserved
Definition: proto_bfd.c:159
static void bfd_sign(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:833
bfd_session_state_t remote_session_state
Definition: proto_bfd.c:99
uint8_t password[16]
Definition: proto_bfd.c:143
128 Bit IPv6 Address.
Definition: radius.h:40
static int bfd_socket_decode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: proto_bfd.c:1630
static int bfd_socket_open(CONF_SECTION *cs, rad_listen_t *this)
Definition: proto_bfd.c:1739
int cf_pair_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, FR_TOKEN dflt_quote)
Parses a CONF_PAIR into a C data type, with a default value.
Definition: conffile.c:1968
void rbtree_free(rbtree_t *tree)
Definition: rbtree.c:84
rlm_rcode_t process_authorize(int type, REQUEST *request)
Definition: modules.c:2098
static int bfd_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
Definition: proto_bfd.c:1665
#define RAD_REQUEST_LVL_DEBUG2
Definition: radiusd.h:315
struct rad_request::@7 log
struct bfd_auth_md5_t bfd_auth_md5_t
bool rbtree_deletebydata(rbtree_t *tree, void const *data)
Delete a node from the tree, based on given data, which MUST have come from rbtree_finddata().
Definition: rbtree.c:496
static void bfd_session_free(void *ctx)
Definition: proto_bfd.c:407
uint8_t auth_len
Definition: proto_bfd.c:157
void exec_trigger(REQUEST *request, CONF_SECTION *cs, char const *name, bool quench) CC_HINT(nonnull(3))
Execute a trigger - call an executable to process an event.
Definition: exec.c:686
uint32_t xmit_auth_seq
Definition: proto_bfd.c:119
int fr_ipaddr_from_sockaddr(struct sockaddr_storage const *sa, socklen_t salen, fr_ipaddr_t *ipaddr, uint16_t *port)
Definition: inet.c:1095
void common_packet_debug(REQUEST *request, RADIUS_PACKET *packet, bool received)
Definition: listen.c:1153
uint8_t detect_multi
Definition: proto_bfd.c:198
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: radius.c:1621
uint32_t local_disc
Definition: proto_bfd.c:101
int doing_poll
Definition: proto_bfd.c:123
fr_ipaddr_t src_ipaddr
Src IP address of packet.
Definition: libradius.h:149
uint32_t sequence_no
Definition: proto_bfd.c:151
#define SHA1_DIGEST_LENGTH
Definition: sha1.h:18
unsigned int version
Definition: proto_bfd.c:188
int fd
Definition: listen.h:77
static int bfd_parse_ip_port(CONF_SECTION *cs, fr_ipaddr_t *ipaddr, uint16_t *port)
Definition: proto_bfd.c:1540
struct bfd_auth_sha1_t bfd_auth_sha1_t
static void bfd_request(bfd_state_t *session, REQUEST *request, RADIUS_PACKET *packet)
Definition: proto_bfd.c:376
uint8_t key_id
Definition: proto_bfd.c:158
static int bfd_stop_poll(bfd_state_t *session)
Definition: proto_bfd.c:1031
fr_event_t * ev_timeout
Definition: proto_bfd.c:92
#define UNUSED
Definition: libradius.h:134
uint32_t min_echo_rx_interval
Definition: proto_bfd.c:204
#define RLM_MODULE_INIT
Definition: modules.h:86
static int bfd_init_sessions(CONF_SECTION *cs, bfd_socket_t *sock, int sockfd)
Definition: proto_bfd.c:1576
void fr_md5_init(FR_MD5_CTX *ctx)
Initialise a new MD5 context.
Definition: md5.c:84
static void bfd_control_packet_init(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:785
#define BFD_AUTH_INVALID
Definition: proto_bfd.c:62
struct timeval last_sent
Definition: proto_bfd.c:96
bfd_auth_sha1_t sha1
Definition: proto_bfd.c:168
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
static int bfd_process(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:1157
static int bfd_authenticate(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:764
void * rbtree_finddata(rbtree_t *tree, void const *data)
Find the user data.
Definition: rbtree.c:537
unsigned int diag
Definition: proto_bfd.c:187
unsigned int final
Definition: proto_bfd.c:194
#define FORWARD
static fr_event_list_t * el
Definition: proto_bfd.c:236
unsigned int auth_present
Definition: proto_bfd.c:192
CONF_SECTION * cf_item_to_section(CONF_ITEM const *item)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: conffile.c:196
fr_event_list_t * fr_event_list_create(TALLOC_CTX *ctx, fr_event_status_t status)
Definition: event.c:120
static int bfd_session_cmp(const void *one, const void *two)
Definition: proto_bfd.c:1636
uint16_t dst_port
DST Port of packet.
Definition: libradius.h:152
union bfd_auth_t bfd_auth_t
uint16_t src_port
Src port of packet.
Definition: libradius.h:151
static int bfd_socket_encode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: proto_bfd.c:1623
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
Definition: libradius.h:150
static void bfd_trigger(bfd_state_t *session)
Definition: proto_bfd.c:392
uint8_t digest[SHA1_DIGEST_LENGTH]
Definition: proto_bfd.c:161
unsigned int demand
Definition: proto_bfd.c:191
int fr_event_fd_insert(fr_event_list_t *el, int type, int fd, fr_event_fd_handler_t handler, void *ctx)
Definition: event.c:324
static int bfd_start_control(bfd_state_t *session)
Definition: proto_bfd.c:978
static int bfd_verify_md5(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:655
void fr_sha1_init(fr_sha1_ctx *context)
Definition: sha1.c:94
static bool stop
Definition: radsnmp.c:48
struct timeval last_recv
Definition: proto_bfd.c:94
void vradlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, va_list ap) CC_HINT(format(printf
bfd_session_state_t
Definition: proto_bfd.c:34
uint32_t detection_time
Definition: proto_bfd.c:126
void fr_md5_update(FR_MD5_CTX *ctx, uint8_t const *in, size_t inlen) CC_BOUNDED(__string__
int af
Address family.
Definition: inet.h:42
const char * server
Definition: proto_bfd.c:69
#define TRANSPORT_UDP
Definition: protocol.h:62
#define rad_assert(expr)
Definition: rad_assert.h:38
uint32_t required_min_rx_interval
Definition: proto_bfd.c:203
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
Definition: token.c:451
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
#define DEBUG(fmt,...)
Definition: log.h:175
rbtree_t * rbtree_create(TALLOC_CTX *ctx, rb_comparator_t compare, rb_free_t node_free, int flags)
Create a new RED-BLACK tree.
Definition: rbtree.c:112
struct bfd_packet_t __attribute__((packed))
Definition: proto_bfd.c:206
static void bfd_auth_md5(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:641
bool remote_demand_mode
Definition: proto_bfd.c:114
bool cf_item_is_section(CONF_ITEM const *item)
Definition: conffile.c:3923
fr_ipaddr_t remote_ipaddr
Definition: proto_bfd.c:82
char const * component
Section the request is in.
Definition: radiusd.h:254
size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
Convert hex strings to binary data.
Definition: misc.c:220
static void bfd_poll_response(bfd_state_t *session)
Definition: proto_bfd.c:1135
uint16_t local_port
Definition: proto_bfd.c:83
bfd_auth_md5_t md5
Definition: proto_bfd.c:167
#define DEBUG2(fmt,...)
Definition: log.h:176
uint8_t digest[MD5_DIGEST_LENGTH]
Definition: proto_bfd.c:152
struct timeval next_recv
Definition: proto_bfd.c:95
RADIUS_PACKET * fr_radius_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new RADIUS_PACKET.
Definition: radius.c:1651
static void bfd_detection_timeout(void *ctx, struct timeval *now)
Definition: proto_bfd.c:1090
union fr_ipaddr_t::@1 ipaddr
#define USEC
Definition: proto_bfd.c:31
unsigned int state
Definition: proto_bfd.c:196
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition: conffile.c:224
uint8_t auth_len
Definition: proto_bfd.c:148
bfd_auth_basic_t basic
Definition: proto_bfd.c:165
uint8_t auth_type
Definition: proto_bfd.c:156
bfd_diag_t local_diag
Definition: proto_bfd.c:104
int number
Definition: proto_bfd.c:65
fr_protocol_t proto_bfd
Definition: proto_bfd.c:1809
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
static void bfd_set_desired_min_tx_interval(bfd_state_t *session, uint32_t value)
Definition: proto_bfd.c:1064
void fr_sha1_final(uint8_t digest[20], fr_sha1_ctx *context)
Definition: sha1.c:132
uint8_t reserved
Definition: proto_bfd.c:150
uint8_t auth_type
Definition: proto_bfd.c:133
uint32_t required_min_rx_interval
Definition: proto_bfd.c:107
static const char * bfd_state[]
Definition: proto_bfd.c:368
A truth value.
Definition: radius.h:56
bfd_auth_type_t auth_type
Definition: proto_bfd.c:77
void rad_suid_up(void)
Definition: util.c:1471
uint32_t desired_min_tx_interval
Definition: proto_bfd.c:202
static int bfd_stop_control(bfd_state_t *session)
Definition: proto_bfd.c:1002
static void bfd_calc_sha1(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:694
32 Bit unsigned integer.
Definition: radius.h:34
unsigned int poll
Definition: proto_bfd.c:195
struct bfd_auth_basic_t bfd_auth_basic_t
char const * fr_strerror(void)
Get the last library error.
Definition: log.c:212
static void bfd_socket_free(rad_listen_t *this)
Definition: proto_bfd.c:1644
uint8_t auth_len
Definition: proto_bfd.c:141
unsigned int control_plane_independent
Definition: proto_bfd.c:193
bfd_socket_t
Definition: proto_bfd.c:228
char const * cf_section_name1(CONF_SECTION const *cs)
Definition: conffile.c:3592
uint32_t next_min_tx_interval
Definition: proto_bfd.c:111
struct bfd_state_t bfd_state_t
unsigned int demand
Definition: proto_bfd.c:195
uint16_t remote_port
Definition: proto_bfd.c:84
uint8_t data[]
Definition: eap_pwd.h:625
int fr_socket_server_base(int proto, fr_ipaddr_t *ipaddr, int *port, char const *port_name, bool async)
Open an IPv4 / IPv6, and UDP / TCP socket, server side.
Definition: socket.c:422
bfd_auth_type_t
Definition: proto_bfd.c:53
fr_ipaddr_t local_ipaddr
Definition: proto_bfd.c:81
socklen_t salen
Definition: proto_bfd.c:90
uint32_t my_min_echo_rx_interval
Definition: proto_bfd.c:124
void cf_log_err(CONF_ITEM const *ci, char const *fmt,...) CC_HINT(format(printf
static int bfd_verify_sha1(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:724
static int bfd_start_poll(bfd_state_t *session)
Definition: proto_bfd.c:1010
uint32_t recv_auth_seq
Definition: proto_bfd.c:118
log_lvl_t rad_debug_lvl
Global debugging level.
Definition: log.c:49
bfd_diag_t
Definition: proto_bfd.c:41
bfd_session_state_t session_state
Definition: proto_bfd.c:98
#define FR_ITEM_POINTER(_t, _p)
Definition: conffile.h:176
static int bfd_socket_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: proto_bfd.c:1616
fr_event_list_t * el
Definition: proto_bfd.c:68
bool rbtree_insert(rbtree_t *tree, void *data)
Definition: rbtree.c:329
static bfd_state_t * bfd_new_session(bfd_socket_t *sock, int sockfd, CONF_SECTION *cs, const fr_ipaddr_t *ipaddr, uint16_t port)
Definition: proto_bfd.c:464
int fr_event_loop(fr_event_list_t *el)
Definition: event.c:507
struct sockaddr_storage remote_sockaddr
Definition: proto_bfd.c:89
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
static char const * secret
Definition: radclient.c:44
uint8_t auth_len
Definition: proto_bfd.c:134
uint8_t key_id
Definition: proto_bfd.c:149
uint32_t remote_disc
Definition: proto_bfd.c:102
uint32_t sequence_no
Definition: proto_bfd.c:160
#define BFD_MAX_SECRET_LENGTH
Definition: proto_bfd.c:32
static const FR_NAME_NUMBER auth_types[]
Definition: proto_bfd.c:1653
int fr_radius_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL digest.
Definition: radius.c:578
CONF_ITEM * cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item)
Return the next item after a CONF_ITEM.
Definition: conffile.c:3850
unsigned int multipoint
Definition: proto_bfd.c:190
void bfd_init(fr_event_list_t *xel)
Definition: proto_bfd.c:240
static void bfd_auth_sha1(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:710
static void bfd_calc_md5(bfd_state_t *session, bfd_packet_t *bfd)
Definition: proto_bfd.c:625
uint32_t desired_min_tx_interval
Definition: proto_bfd.c:106
fr_event_t * ev_packet
Definition: proto_bfd.c:93
int detect_multi
Definition: proto_bfd.c:116
int fr_event_delete(fr_event_list_t *el, fr_event_t **parent)
Definition: event.c:172
static void bfd_set_timeout(bfd_state_t *session, struct timeval *when)
Definition: proto_bfd.c:939
void void fr_md5_final(uint8_t out[MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx) CC_BOUNDED(__minbytes__
bfd_auth_simple_t password
Definition: proto_bfd.c:166
bfd_auth_t auth
Definition: proto_bfd.c:205
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
static void bfd_send_packet(void *ctx, UNUSED struct timeval *now)
Definition: proto_bfd.c:860
uint64_t magic
Used to validate loaded library.
Definition: protocol.h:40
IPv4/6 prefix.
Definition: inet.h:41
void void MD5_DIGEST_LENGTH
Definition: md5.h:65
uint32_t remote_min_echo_rx_interval
Definition: proto_bfd.c:109
int detection_timeouts
Definition: proto_bfd.c:127
void * data
Definition: listen.h:103
uint8_t auth_type
Definition: proto_bfd.c:147
static int bfd_verify_sequence(bfd_state_t *session, uint32_t sequence_no, int keyed)
Definition: proto_bfd.c:598
int fr_socket_server_bind(int sockfd, fr_ipaddr_t *ipaddr, int *port, char const *interface)
Bind to an IPv4 / IPv6, and UDP / TCP socket, server side.
Definition: socket.c:615
static int bfd_socket_print(const rad_listen_t *this, char *buffer, size_t bufsize)
Definition: proto_bfd.c:1781
String of printable characters.
Definition: radius.h:33
size_t secret_len
Definition: proto_bfd.c:79
int fr_event_insert(fr_event_list_t *el, fr_event_callback_t callback, void *ctx, struct timeval *when, fr_event_t **parent)
Definition: event.c:204
uint32_t remote_min_rx_interval
Definition: proto_bfd.c:108
uint32_t your_disc
Definition: proto_bfd.c:201
uint8_t auth_type
Definition: proto_bfd.c:140
static int bfd_start_packets(bfd_state_t *session)
Definition: proto_bfd.c:886
char const * fr_inet_ntoh(fr_ipaddr_t const *src, char *out, size_t outlen)
Perform reverse resolution of an IP address.
Definition: inet.c:226
32 Bit IPv4 Address.
Definition: radius.h:35
char const * module
Module the request is currently being processed by.
Definition: radiusd.h:253
int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition: inet.c:1026
bool demand_mode
Definition: proto_bfd.c:113
static int bfd_socket_recv(rad_listen_t *listener)
Definition: proto_bfd.c:1415
#define ERROR(fmt,...)
Definition: log.h:145
16 Bit unsigned integer.
Definition: radius.h:43
REQUEST * request_alloc(TALLOC_CTX *ctx)
Create a new REQUEST data structure.
Definition: request.c:85
char const * server
Definition: radiusd.h:289
uint8_t length
Definition: proto_bfd.c:199
int fr_ipaddr_to_sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port, struct sockaddr_storage *sa, socklen_t *salen)
Definition: inet.c:1057
int auth_seq_known
Definition: proto_bfd.c:121
uint8_t secret[BFD_MAX_SECRET_LENGTH]
Definition: proto_bfd.c:78
struct bfd_auth_simple_t bfd_auth_simple_t