All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
realms.c
Go to the documentation of this file.
1 /*
2  * realms.c Realm handling code
3  *
4  * Version: $Id: d2cb98d8ccbe4fdf0c2b8c47158bd7c7efb74367 $
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 2007 The FreeRADIUS server project
21  * Copyright 2007 Alan DeKok <aland@deployingradius.com>
22  */
23 
24 RCSID("$Id: d2cb98d8ccbe4fdf0c2b8c47158bd7c7efb74367 $")
25 
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/realms.h>
28 #include <freeradius-devel/rad_assert.h>
29 #include <freeradius-devel/net.h>
30 
31 #include <sys/stat.h>
32 
33 #include <ctype.h>
34 #include <fcntl.h>
35 
36 static rbtree_t *realms_byname = NULL;
37 #ifdef WITH_TCP
38 bool home_servers_udp = false;
39 #endif
40 
41 #ifdef HAVE_REGEX
42 typedef struct realm_regex realm_regex_t;
43 
44 /** Regular expression associated with a realm
45  *
46  */
47 struct realm_regex {
48  REALM *realm; //!< The realm this regex matches.
49  regex_t *preg; //!< The pre-compiled regular expression.
50  realm_regex_t *next; //!< The next realm in the list of regular expressions.
51 };
52 static realm_regex_t *realms_regex = NULL;
53 #endif /* HAVE_REGEX */
54 
55 struct realm_config {
57  uint32_t dead_time;
58  uint32_t retry_count;
59  uint32_t retry_delay;
60  bool dynamic;
61  bool fallback;
63 };
64 
66  { "auth", HOME_TYPE_AUTH },
67  { "acct", HOME_TYPE_ACCT },
68  { "auth+acct", HOME_TYPE_AUTH_ACCT },
69  { "coa", HOME_TYPE_COA },
70  { NULL, 0 }
71 };
72 
73 static const FR_NAME_NUMBER home_ping_check[] = {
74  { "none", HOME_PING_CHECK_NONE },
75  { "status-server", HOME_PING_CHECK_STATUS_SERVER },
76  { "request", HOME_PING_CHECK_REQUEST },
77  { NULL, 0 }
78 };
79 
81 
82 #ifdef WITH_PROXY
85 #ifdef WITH_STATS
86 static int home_server_max_number = 0;
88 #endif
89 
90 static rbtree_t *home_pools_byname = NULL;
91 
92 /*
93  * Map the proxy server configuration parameters to variables.
94  */
95 static const CONF_PARSER proxy_config[] = {
96  { FR_CONF_OFFSET("retry_delay", PW_TYPE_INTEGER, realm_config_t, retry_delay), .dflt = STRINGIFY(RETRY_DELAY) },
97 
98  { FR_CONF_OFFSET("retry_count", PW_TYPE_INTEGER, realm_config_t, retry_count), .dflt = STRINGIFY(RETRY_COUNT) },
99 
100  { FR_CONF_OFFSET("default_fallback", PW_TYPE_BOOLEAN, realm_config_t, fallback), .dflt = "no" },
101 
102  { FR_CONF_OFFSET("dynamic", PW_TYPE_BOOLEAN, realm_config_t, dynamic) },
103 
104  { FR_CONF_OFFSET("dead_time", PW_TYPE_INTEGER, realm_config_t, dead_time), .dflt = STRINGIFY(DEAD_TIME) },
105 
106  { FR_CONF_OFFSET("wake_all_if_all_dead", PW_TYPE_BOOLEAN, realm_config_t, wake_all_if_all_dead), .dflt = "no" },
108 };
109 #endif
110 
111 static int realm_name_cmp(void const *one, void const *two)
112 {
113  REALM const *a = one;
114  REALM const *b = two;
115 
116  return strcasecmp(a->name, b->name);
117 }
118 
119 
120 #ifdef WITH_PROXY
121 static void home_server_free(void *data)
122 {
123  home_server_t *home = talloc_get_type_abort(data, home_server_t);
124 
125  talloc_free(home);
126 }
127 
128 static int home_server_name_cmp(void const *one, void const *two)
129 {
130  home_server_t const *a = one;
131  home_server_t const *b = two;
132 
133  if (a->type < b->type) return -1;
134  if (a->type > b->type) return +1;
135 
136  return strcasecmp(a->name, b->name);
137 }
138 
139 static int home_server_addr_cmp(void const *one, void const *two)
140 {
141  int rcode;
142  home_server_t const *a = one;
143  home_server_t const *b = two;
144 
145  if (a->server && !b->server) return -1;
146  if (!a->server && b->server) return +1;
147  if (a->server && b->server) {
148  rcode = a->type - b->type;
149  if (rcode != 0) return rcode;
150  return strcmp(a->server, b->server);
151  }
152 
153  if (a->port < b->port) return -1;
154  if (a->port > b->port) return +1;
155 
156 #ifdef WITH_TCP
157  if (a->proto < b->proto) return -1;
158  if (a->proto > b->proto) return +1;
159 #endif
160 
161  rcode = fr_ipaddr_cmp(&a->src_ipaddr, &b->src_ipaddr);
162  if (rcode != 0) return rcode;
163 
164  return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
165 }
166 
167 #ifdef WITH_STATS
168 static int home_server_number_cmp(void const *one, void const *two)
169 {
170  home_server_t const *a = one;
171  home_server_t const *b = two;
172 
173  return (a->number - b->number);
174 }
175 #endif
176 
177 static int home_pool_name_cmp(void const *one, void const *two)
178 {
179  home_pool_t const *a = one;
180  home_pool_t const *b = two;
181 
182  if (a->server_type < b->server_type) return -1;
183  if (a->server_type > b->server_type) return +1;
184 
185  return strcasecmp(a->name, b->name);
186 }
187 
188 
189 static size_t CC_HINT(nonnull) xlat_cs(CONF_SECTION *cs, char const *fmt, char *out, size_t outlen)
190 {
191  char const *value = NULL;
192 
193  /*
194  * Instance name
195  */
196  if (strcmp(fmt, "instance") == 0) {
197  value = cf_section_name2(cs);
198  if (!value) {
199  *out = '\0';
200  return 0;
201  }
202  } else {
203  CONF_PAIR *cp;
204 
205  cp = cf_pair_find(cs, fmt);
206  if (!cp || !(value = cf_pair_value(cp))) {
207  *out = '\0';
208  return 0;
209  }
210  }
211 
212  strlcpy(out, value, outlen);
213 
214  return strlen(out);
215 }
216 
217 
218 /** xlat for %{home_server:foo}
219  *
220  */
221 static ssize_t xlat_home_server(char **out, size_t outlen,
222  UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
223  REQUEST *request, char const *fmt) CC_HINT(nonnull);
224 static ssize_t xlat_home_server(char **out, size_t outlen,
225  UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
226  REQUEST *request, char const *fmt)
227 {
228  if (!request->home_server) {
229  RWDEBUG("No home_server associated with this request");
230  return 0;
231  }
232 
233  return xlat_cs(request->home_server->cs, fmt, *out, outlen);
234 }
235 
236 
237 /** xlat for %{home_server_pool:foo}
238  *
239  */
240 static ssize_t xlat_server_pool(char **out, size_t outlen,
241  UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
242  REQUEST *request, char const *fmt) CC_HINT(nonnull);
243 static ssize_t xlat_server_pool(char **out, size_t outlen,
244  UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
245  REQUEST *request, char const *fmt)
246 {
247  if (!request->home_pool) {
248  RWDEBUG("No home_pool associated with this request");
249  return 0;
250  }
251 
252  return xlat_cs(request->home_pool->cs, fmt, *out, outlen);
253 }
254 #endif
255 
256 void realms_free(void)
257 {
258 #ifdef WITH_PROXY
259 # ifdef WITH_STATS
260  rbtree_free(home_servers_bynumber);
261  home_servers_bynumber = NULL;
262 # endif
263 
264  rbtree_free(home_servers_byname);
265  home_servers_byname = NULL;
266 
267  rbtree_free(home_servers_byaddr);
268  home_servers_byaddr = NULL;
269 
270  rbtree_free(home_pools_byname);
271  home_pools_byname = NULL;
272 #endif
273 
274  rbtree_free(realms_byname);
275  realms_byname = NULL;
276 
277  realm_pool_free(NULL);
278 
279  talloc_free(realm_config);
280  realm_config = NULL;
281 }
282 
283 
284 #ifdef WITH_PROXY
286  { FR_CONF_OFFSET("max_connections", PW_TYPE_INTEGER, home_server_t, limit.max_connections), .dflt = "16" },
287  { FR_CONF_OFFSET("max_requests", PW_TYPE_INTEGER, home_server_t, limit.max_requests), .dflt = "0" },
288  { FR_CONF_OFFSET("lifetime", PW_TYPE_INTEGER, home_server_t, limit.lifetime), .dflt = "0" },
289  { FR_CONF_OFFSET("idle_timeout", PW_TYPE_INTEGER, home_server_t, limit.idle_timeout), .dflt = "0" },
291 };
292 
293 #ifdef WITH_COA
295  { FR_CONF_OFFSET("irt", PW_TYPE_INTEGER, home_server_t, coa_irt), .dflt = STRINGIFY(2) },
296  { FR_CONF_OFFSET("mrt", PW_TYPE_INTEGER, home_server_t, coa_mrt), .dflt = STRINGIFY(16) },
297  { FR_CONF_OFFSET("mrc", PW_TYPE_INTEGER, home_server_t, coa_mrc), .dflt = STRINGIFY(5) },
298  { FR_CONF_OFFSET("mrd", PW_TYPE_INTEGER, home_server_t, coa_mrd), .dflt = STRINGIFY(30) },
300 };
301 #endif
302 
304  { FR_CONF_OFFSET("ipaddr", PW_TYPE_COMBO_IP_ADDR, home_server_t, ipaddr) },
305  { FR_CONF_OFFSET("ipv4addr", PW_TYPE_IPV4_ADDR, home_server_t, ipaddr) },
306  { FR_CONF_OFFSET("ipv6addr", PW_TYPE_IPV6_ADDR, home_server_t, ipaddr) },
307  { FR_CONF_OFFSET("virtual_server", PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, server) },
308 
309  { FR_CONF_OFFSET("port", PW_TYPE_SHORT, home_server_t, port), .dflt = "0" },
310 
311  { FR_CONF_OFFSET("type", PW_TYPE_STRING, home_server_t, type_str) },
312 
313 #ifdef WITH_TCP
314  { FR_CONF_OFFSET("proto", PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, proto_str) },
315 #endif
316 
318 
319  { FR_CONF_OFFSET("src_ipaddr", PW_TYPE_STRING, home_server_t, src_ipaddr_str) },
320 
321  { FR_CONF_OFFSET("response_window", PW_TYPE_TIMEVAL, home_server_t, response_window), .dflt = "30" },
322  { FR_CONF_OFFSET("response_timeouts", PW_TYPE_INTEGER, home_server_t, max_response_timeouts), .dflt = "1" },
323  { FR_CONF_OFFSET("max_outstanding", PW_TYPE_INTEGER, home_server_t, max_outstanding), .dflt = "65536" },
324 
325  { FR_CONF_OFFSET("zombie_period", PW_TYPE_INTEGER, home_server_t, zombie_period), .dflt = "40" },
326 
327  { FR_CONF_OFFSET("status_check", PW_TYPE_STRING, home_server_t, ping_check_str), .dflt = "none" },
328  { FR_CONF_OFFSET("ping_check", PW_TYPE_STRING, home_server_t, ping_check_str) },
329 
330  { FR_CONF_OFFSET("ping_interval", PW_TYPE_INTEGER, home_server_t, ping_interval), .dflt = "30" },
331  { FR_CONF_OFFSET("check_interval", PW_TYPE_INTEGER, home_server_t, ping_interval) },
332 
333  { FR_CONF_OFFSET("check_timeout", PW_TYPE_INTEGER, home_server_t, ping_timeout), .dflt = "4" },
334  { FR_CONF_OFFSET("status_check_timeout", PW_TYPE_INTEGER, home_server_t, ping_timeout) },
335 
336  { FR_CONF_OFFSET("num_answers_to_alive", PW_TYPE_INTEGER, home_server_t, num_pings_to_alive), .dflt = "3" },
337  { FR_CONF_OFFSET("revive_interval", PW_TYPE_INTEGER, home_server_t, revive_interval), .dflt = "300" },
338 
339  { FR_CONF_OFFSET("username", PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, ping_user_name) },
340  { FR_CONF_OFFSET("password", PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, ping_user_password) },
341 
342 #ifdef WITH_STATS
343  { FR_CONF_OFFSET("historic_average_window", PW_TYPE_INTEGER, home_server_t, ema.window) },
344 #endif
345 
346  { FR_CONF_POINTER("limit", PW_TYPE_SUBSECTION, NULL), .dflt = (void const *) limit_config },
347 
348 #ifdef WITH_COA
349  { FR_CONF_POINTER("coa", PW_TYPE_SUBSECTION, NULL), .dflt = (void const *) home_server_coa },
350 #endif
352 };
353 
354 
355 static void null_free(UNUSED void *data)
356 {
357 }
358 
359 /*
360  * Ensure that all of the parameters in the home server are OK.
361  */
363 {
364  CONF_SECTION *parent = NULL;
365 
366  FR_INTEGER_BOUND_CHECK("max_outstanding", home->max_outstanding, >=, 8);
367  FR_INTEGER_BOUND_CHECK("max_outstanding", home->max_outstanding, <=, 65536*16);
368 
369  FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, >=, 6);
370  FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, <=, 120);
371 
372  FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, >=, 0, 1000);
373  FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, 60, 0);
374  FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=,
376 
377  FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, >=, 1);
378  FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, <=, 1000);
379 
380  /*
381  * Track the minimum response window, so that we can
382  * correctly set the timers in process.c
383  */
384  if (timercmp(&main_config.init_delay, &home->response_window, >)) {
386  }
387 
388  FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, >=, 1);
389  FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, <=, 120);
390  FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, >=, (uint32_t) home->response_window.tv_sec);
391 
392  FR_INTEGER_BOUND_CHECK("num_pings_to_alive", home->num_pings_to_alive, >=, 3);
393  FR_INTEGER_BOUND_CHECK("num_pings_to_alive", home->num_pings_to_alive, <=, 10);
394 
395  FR_INTEGER_BOUND_CHECK("check_timeout", home->ping_timeout, >=, 1);
396  FR_INTEGER_BOUND_CHECK("check_timeout", home->ping_timeout, <=, 10);
397 
398  FR_INTEGER_BOUND_CHECK("revive_interval", home->revive_interval, >=, 60);
399  FR_INTEGER_BOUND_CHECK("revive_interval", home->revive_interval, <=, 3600);
400 
401 #ifdef WITH_COA
402  FR_INTEGER_BOUND_CHECK("coa_irt", home->coa_irt, >=, 1);
403  FR_INTEGER_BOUND_CHECK("coa_irt", home->coa_irt, <=, 5);
404 
405  FR_INTEGER_BOUND_CHECK("coa_mrc", home->coa_mrc, <=, 20);
406 
407  FR_INTEGER_BOUND_CHECK("coa_mrt", home->coa_mrt, <=, 30);
408 
409  FR_INTEGER_BOUND_CHECK("coa_mrd", home->coa_mrd, >=, 5);
410  FR_INTEGER_BOUND_CHECK("coa_mrd", home->coa_mrd, <=, 60);
411 #endif
412 
413  FR_INTEGER_BOUND_CHECK("max_connections", home->limit.max_connections, <=, 1024);
414 
415 #ifdef WITH_TCP
416  /*
417  * UDP sockets can't be connection limited.
418  */
419  if (home->proto != IPPROTO_TCP) home->limit.max_connections = 0;
420 #endif
421 
422  if ((home->limit.idle_timeout > 0) && (home->limit.idle_timeout < 5))
423  home->limit.idle_timeout = 5;
424  if ((home->limit.lifetime > 0) && (home->limit.lifetime < 5))
425  home->limit.lifetime = 5;
426  if ((home->limit.lifetime > 0) && (home->limit.idle_timeout > home->limit.lifetime))
427  home->limit.idle_timeout = 0;
428 
429  /*
430  * Make sure that this is set.
431  */
432  if (home->src_ipaddr.af == AF_UNSPEC) {
433  home->src_ipaddr.af = home->ipaddr.af;
434  }
435 
436  parent = cf_item_parent(cf_section_to_item(cs));
437  if (parent && strcmp(cf_section_name1(parent), "server") == 0) {
438  home->parent_server = cf_section_name2(parent);
439  }
440 }
441 
442 /** Insert a new home server into the various internal lookup trees
443  *
444  * @param home server to add.
445  * @param cs That defined the home server.
446  * @return
447  * - true on success.
448  * - false on failure.
449  */
451 {
452  if (home->name && !rbtree_insert(home_servers_byname, home)) {
453  cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name);
454  return false;
455  }
456 
457  if (!home->server && !rbtree_insert(home_servers_byaddr, home)) {
458  rbtree_deletebydata(home_servers_byname, home);
459  cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name);
460  return false;
461  }
462 
463 #ifdef WITH_STATS
464  home->number = home_server_max_number++;
465  if (!rbtree_insert(home_servers_bynumber, home)) {
466  rbtree_deletebydata(home_servers_byname, home);
467  if (home->ipaddr.af != AF_UNSPEC) {
468  rbtree_deletebydata(home_servers_byname, home);
469  }
470  cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name);
471  return false;
472  }
473 #endif
474 
475  return true;
476 }
477 
478 /** Add an already allocate home_server_t to the various trees
479  *
480  * @param home server to add.
481  * @return
482  * - true on success.
483  * - false on error.
484  */
486 {
487  /*
488  * The structs aren't mutex protected. Refuse to destroy
489  * the server.
490  */
491  if (event_loop_started && !realm_config->dynamic) {
492  ERROR("Failed to add dynamic home server, \"dynamic = yes\" must be set in proxy.conf");
493  return false;
494  }
495 
496  if (home->name && (rbtree_finddata(home_servers_byname, home) != NULL)) {
497  cf_log_err_cs(home->cs, "Duplicate home server name %s", home->name);
498  return false;
499  }
500 
501  if (!home->server && (rbtree_finddata(home_servers_byaddr, home) != NULL)) {
502  char buffer[INET6_ADDRSTRLEN];
503 
504  inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr, buffer, sizeof(buffer));
505 
506  cf_log_err_cs(home->cs, "Duplicate home server address%s%s%s: %s:%s%s/%i",
507  home->name ? " (already in use by " : "",
508  home->name ? home->name : "",
509  home->name ? ")" : "",
510  buffer,
511  fr_int2str(fr_net_ip_proto_table, home->proto, "<INVALID>"),
512 #ifdef WITH_TLS
513  home->tls ? "+tls" : "",
514 #else
515  "",
516 #endif
517  home->port);
518 
519  return false;
520  }
521 
522  if (!home_server_insert(home, home->cs)) return false;
523 
524  /*
525  * Dual home servers cause us to auto-create an
526  * accounting server for UDP sockets, and leave
527  * everything alone for TLS sockets.
528  */
529  if (home->dual
530 #ifdef WITH_TLS
531  && !home->tls
532 #endif
533 ) {
534  home_server_t *home2 = talloc(talloc_parent(home), home_server_t);
535 
536  memcpy(home2, home, sizeof(*home2));
537 
538  home2->type = HOME_TYPE_ACCT;
539  home2->dual = true;
540  home2->port++;
541 
542  home2->ping_user_password = NULL;
543  home2->cs = home->cs;
544  home2->parent_server = home->parent_server;
545 
546  if (!home_server_insert(home2, home->cs)) {
547  talloc_free(home2);
548  return false;
549  }
550  }
551 
552  /*
553  * Mark it as already processed
554  */
555  cf_data_add(home->cs, "home_server", (void *)null_free, null_free);
556 
557  return true;
558 }
559 
560 /** Alloc a new home server defined by a #CONF_SECTION
561  *
562  * @param ctx to allocate home_server_t in.
563  * @param rc Realm config, may be NULL in which case the global realm_config will be used.
564  * @param cs Configuration section containing home server parameters.
565  * @return
566  * - New #home_server_t alloced in the context of the realm_config.
567  * - NULL on error.
568  */
570 {
571  home_server_t *home;
572  CONF_SECTION *tls;
573 
574  if (!rc) rc = realm_config; /* Use the global config */
575 
576  home = talloc_zero(ctx, home_server_t);
577  home->name = cf_section_name2(cs);
578  home->log_name = talloc_typed_strdup(home, home->name);
579  home->cs = cs;
580  home->state = HOME_STATE_UNKNOWN;
581  home->proto = IPPROTO_UDP;
582 
583  /*
584  * Parse the configuration into the home server
585  * struct.
586  */
587  if (cf_section_parse(cs, home, home_server_config) < 0) goto error;
588 
589  /*
590  * It has an IP address, it must be a remote server.
591  */
592  if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) {
593  if (fr_is_inaddr_any(&home->ipaddr) == 1) {
594  cf_log_err_cs(cs, "Wildcard '*' addresses are not permitted for home servers");
595  goto error;
596  }
597 
598  if (!home->log_name) {
599  char buffer[FR_IPADDR_PREFIX_STRLEN];
600 
601  fr_inet_ntop_prefix(buffer, sizeof(buffer), &home->ipaddr);
602 
603  home->log_name = talloc_asprintf(home, "%s:%i", buffer, home->port);
604  }
605  /*
606  * If it has a 'virtual_Server' config item, it's
607  * a loopback into a virtual server.
608  */
609  } else if (cf_pair_find(cs, "virtual_server") != NULL) {
610  home->ipaddr.af = AF_UNSPEC; /* mark ipaddr as unused */
611 
612  if (!home->server) {
613  cf_log_err_cs(cs, "Invalid value for virtual_server");
614  goto error;
615  }
616 
617  /*
618  * Try and find a 'server' section off the root of
619  * the config with a name that matches the
620  * virtual_server.
621  */
622  if (!cf_section_sub_find_name2(rc->cs, "server", home->server)) {
623  cf_log_err_cs(cs, "No such server %s", home->server);
624  goto error;
625  }
626 
627  home->secret = "";
628  home->log_name = talloc_typed_strdup(home, home->server);
629  /*
630  * Otherwise it's an invalid config section and we
631  * raise an error.
632  */
633  } else {
634  cf_log_err_cs(cs, "No ipaddr, ipv4addr, ipv6addr, or virtual_server defined "
635  "for home server");
636  error:
637  talloc_free(home);
638  return false;
639  }
640 
641  {
643 
644  if (home->type_str) type = fr_str2int(home_server_types, home->type_str, HOME_TYPE_INVALID);
645 
646  home->type = type;
647 
648  switch (type) {
649  case HOME_TYPE_AUTH_ACCT:
650  home->dual = true;
651  break;
652 
653  case HOME_TYPE_AUTH:
654  case HOME_TYPE_ACCT:
655  break;
656 
657 #ifdef WITH_COA
658  case HOME_TYPE_COA:
659  if (home->server != NULL) {
660  cf_log_err_cs(cs, "Home servers of type \"coa\" cannot point to a virtual server");
661  goto error;
662  }
663  break;
664 #endif
665 
666  case HOME_TYPE_INVALID:
667  cf_log_err_cs(cs, "Invalid type \"%s\" for home server %s", home->type_str, home->log_name);
668  goto error;
669  }
670  }
671 
672  {
674 
675  if (home->ping_check_str) type = fr_str2int(home_ping_check, home->ping_check_str,
677 
678  switch (type) {
681  break;
682 
684  if (!home->ping_user_name) {
685  cf_log_err_cs(cs, "You must supply a 'username' to enable status_check=request");
686  goto error;
687  }
688 
689  if ((home->type == HOME_TYPE_AUTH) && !home->ping_user_password) {
690  cf_log_err_cs(cs, "You must supply a 'password' to enable status_check=request");
691  goto error;
692  }
693 
694  break;
695 
697  cf_log_err_cs(cs, "Invalid status_check \"%s\" for home server %s",
698  home->ping_check_str, home->log_name);
699  goto error;
700  }
701 
702  home->ping_check = type;
703  }
704 
705  {
706  int proto = IPPROTO_UDP;
707 
708  if (home->proto_str) proto = fr_str2int(fr_net_ip_proto_table, home->proto_str, -1);
709 
710  switch (proto) {
711  case IPPROTO_UDP:
712  home_servers_udp = true;
713  break;
714 
715  case IPPROTO_TCP:
716 #ifndef WITH_TCP
717  cf_log_err_cs(cs, "Server not built with support for RADIUS over TCP");
718  goto error;
719 #endif
720  if (home->ping_check != HOME_PING_CHECK_NONE) {
721  cf_log_err_cs(cs, "Only 'status_check = none' is allowed for home "
722  "servers with 'proto = tcp'");
723  goto error;
724  }
725  break;
726 
727  default:
728  cf_log_err_cs(cs, "Unknown proto \"%s\"", home->proto_str);
729  goto error;
730  }
731 
732  home->proto = proto;
733  }
734 
735  if (!home->server && rbtree_finddata(home_servers_byaddr, home)) {
736  cf_log_err_cs(cs, "Duplicate home server");
737  goto error;
738  }
739 
740  /*
741  * Check the TLS configuration.
742  */
743  tls = cf_section_sub_find(cs, "tls");
744 #ifndef WITH_TLS
745  if (tls) {
746  cf_log_err_cs(cs, "TLS transport is not available in this executable");
747  goto error;
748  }
749 #endif
750 
751  /*
752  * If were doing RADSEC (tls+tcp) the secret should default
753  * to radsec, else a secret must be set.
754  */
755  if (!home->secret) {
756 #ifdef WITH_TLS
757  if (tls && (home->proto == IPPROTO_TCP)) {
758  home->secret = "radsec";
759  } else
760 #endif
761  {
762  cf_log_err_cs(cs, "No shared secret defined for home server %s", home->log_name);
763  goto error;
764  }
765  }
766 
767  /*
768  * Virtual servers have some TLS restrictions.
769  */
770  if (home->server) {
771  if (tls) {
772  cf_log_err_cs(cs, "Virtual home_servers cannot have a \"tls\" subsection");
773  goto error;
774  }
775  } else {
776  /*
777  * If the home is not a virtual server, guess the port
778  * and look up the source ip address.
779  */
780  rad_assert(home->ipaddr.af != AF_UNSPEC);
781 
782 #ifdef WITH_TLS
783  if (tls && (home->proto != IPPROTO_TCP)) {
784  cf_log_err_cs(cs, "TLS transport is not available for UDP sockets");
785  goto error;
786  }
787 #endif
788 
789  /*
790  * Set the default port if necessary.
791  */
792  if (home->port == 0) {
793  char buffer[FR_IPADDR_PREFIX_STRLEN];
794 
795  /*
796  * For RADSEC we use the special RADIUS over TCP/TLS port
797  * for both accounting and authentication, but for some
798  * bizarre reason for RADIUS over plain TCP we use separate
799  * ports 1812 and 1813.
800  */
801 #ifdef WITH_TLS
802  if (tls) {
803  home->port = PW_RADIUS_TLS_PORT;
804  } else
805 #endif
806  switch (home->type) {
807  default:
808  rad_assert(0);
809  /* FALL-THROUGH */
810 
811  case HOME_TYPE_AUTH:
812  home->port = PW_AUTH_UDP_PORT;
813  break;
814 
815  case HOME_TYPE_ACCT:
816  home->port = PW_ACCT_UDP_PORT;
817  break;
818 
819  case HOME_TYPE_COA:
820  home->port = PW_COA_UDP_PORT;
821  break;
822  }
823 
824  /*
825  * Now that we have a real port, use that.
826  */
827  rad_const_free(home->log_name);
828 
829  fr_inet_ntop_prefix(buffer, sizeof(buffer), &home->ipaddr);
830 
831  home->log_name = talloc_asprintf(home, "%s:%i", buffer, home->port);
832  }
833 
834  /*
835  * If we have a src_ipaddr_str resolve it to
836  * the same address family as the destination
837  * IP.
838  */
839  if (home->src_ipaddr_str) {
840  if (fr_inet_hton(&home->src_ipaddr, home->ipaddr.af, home->src_ipaddr_str, false) < 0) {
841  cf_log_err_cs(cs, "Failed parsing src_ipaddr");
842  goto error;
843  }
844  /*
845  * Source isn't specified, set it to the
846  * correct address family, but leave it as
847  * zeroes.
848  */
849  } else {
850  home->src_ipaddr.af = home->ipaddr.af;
851  }
852 
853 #ifdef WITH_TLS
854  /*
855  * Parse the SSL client configuration.
856  */
857  if (tls) {
858  home->tls = tls_client_conf_parse(tls);
859  if (!home->tls) {
860  goto error;
861  }
862  }
863 #endif
864  } /* end of parse home server */
865 
866  realm_home_server_sanitize(home, cs);
867 
868  return home;
869 }
870 
871 /** Fixup a client configuration section to specify a home server
872  *
873  * This is used to create the equivalent CoA home server entry for a client,
874  * so that the server can originate CoA messages.
875  *
876  * The server section automatically inherits the following fields from the client:
877  * - ipaddr/ipv4addr/ipv6addr
878  * - secret
879  * - src_ipaddr
880  *
881  * @note new CONF_SECTION will be allocated in the context of the client, but the client
882  * C#ONF_SECTION will not be modified.
883  *
884  * @param client CONF_SECTION to inherit values from.
885  * @return
886  * - A new server #CONF_SECTION.
887  * - A pointer to the existing #CONF_SECTION in the client.
888  */
890 {
891  CONF_SECTION *server, *cs;
892  CONF_PAIR *cp;
893 
894  /*
895  * Alloc a plain home server for both cases
896  *
897  * There's no way these can be referenced by a pool,
898  * and they may conflict with home servers in proxy.conf
899  * so it's easier to not set a name.
900  */
901 
902  /*
903  *
904  * Duplicate the server section, so we don't mangle
905  * the client CONF_SECTION we were passed.
906  */
907  cs = cf_section_sub_find(client, "coa_server");
908  if (cs) {
909  server = cf_section_dup(client, cs, "home_server", NULL, true);
910  } else {
911  server = cf_section_alloc(client, "home_server", cf_section_name2(client));
912  }
913 
914  if (!cs || (!cf_pair_find(cs, "ipaddr") && !cf_pair_find(cs, "ipv4addr") && !cf_pair_find(cs, "ipv6addr"))) {
915  cp = cf_pair_find(client, "ipaddr");
916  if (!cp) cp = cf_pair_find(client, "ipv4addr");
917  if (!cp) cp = cf_pair_find(client, "ipv6addr");
918 
919  cf_pair_add(server, cf_pair_dup(server, cp));
920  }
921 
922  if (!cs || !cf_pair_find(cs, "secret")) {
923  cp = cf_pair_find(client, "secret");
924  if (cp) cf_pair_add(server, cp);
925  }
926 
927  if (!cs || !cf_pair_find(cs, "src_ipaddr")) {
928  cp = cf_pair_find(client, "src_ipaddr");
929  if (cp) cf_pair_add(server, cf_pair_dup(server, cp));
930  }
931 
932  if (!cs || !(cp = cf_pair_find(cs, "type"))) {
933  cp = cf_pair_alloc(server, "type", "coa", T_OP_EQ, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
934  if (cp) cf_pair_add(server, cf_pair_dup(server, cp));
935  } else if (strcmp(cf_pair_value(cp), "coa") != 0) {
936  talloc_free(server);
937  cf_log_err_cs(server, "server.type must be \"coa\"");
938  return NULL;
939  }
940 
941  return server;
942 }
943 
945  home_type_t server_type, int num_home_servers)
946 {
947  home_pool_t *pool;
948 
949  /*
950  * FIXME: Move to two separate structs, which allows
951  * for re-alloc.
952  */
953  pool = talloc_size(rc, sizeof(*pool) + (sizeof(pool->servers[0]) * num_home_servers));
954  if (!pool) return NULL; /* just for pairanoia */
955 
956  memset(pool, 0, sizeof(*pool) + (sizeof(pool->servers[0]) * num_home_servers));
957  pool->name = name;
958  pool->type = type;
959  pool->server_type = server_type;
960  pool->num_home_servers = num_home_servers;
961 
962  return pool;
963 }
964 
965 /*
966  * Ensure any home_server clauses in a home_server_pool section reference
967  * defined home servers, which should already have been created, regardless
968  * of where they appear in the configuration.
969  */
971  char const *name, home_type_t server_type,
972  home_server_t **phome)
973 {
974  home_server_t myhome, *home;
975 
976  if (!name) {
977  cf_log_err_cp(cp,
978  "No value given for home_server");
979  return 0;
980  }
981 
982  myhome.name = name;
983  myhome.type = server_type;
984  home = rbtree_finddata(home_servers_byname, &myhome);
985  if (home) {
986  *phome = home;
987  return 1;
988  }
989 
990  switch (server_type) {
991  case HOME_TYPE_AUTH:
992  case HOME_TYPE_ACCT:
993  myhome.type = HOME_TYPE_AUTH_ACCT;
994  home = rbtree_finddata(home_servers_byname, &myhome);
995  if (home) {
996  *phome = home;
997  return 1;
998  }
999  break;
1000 
1001  default:
1002  break;
1003  }
1004 
1005  cf_log_err_cp(cp, "Unknown home_server \"%s\".", name);
1006  return 0;
1007 }
1008 
1009 
1010 #ifndef HAVE_PTHREAD_H
1012 {
1013  if (!event_loop_started || !realm_config->dynamic) return;
1014 
1015  talloc_free(pool);
1016 }
1017 #else /* HAVE_PTHREAD_H */
1018 typedef struct pool_list_t pool_list_t;
1019 
1020 struct pool_list_t {
1021  pool_list_t *next;
1022  home_pool_t *pool;
1023  time_t when;
1024 };
1025 
1026 static bool pool_free_init = false;
1027 static pthread_mutex_t pool_free_mutex;
1028 static pool_list_t *pool_list = NULL;
1029 
1030 void realm_pool_free(home_pool_t *pool)
1031 {
1032  int i;
1033  time_t now;
1034  pool_list_t *this, **last;
1035 
1036  if (!event_loop_started) return;
1037  if (!realm_config->dynamic) return;
1038 
1039  if (pool) {
1040  /*
1041  * Double-check that the realm wasn't loaded from the
1042  * configuration files.
1043  */
1044  for (i = 0; i < pool->num_home_servers; i++) {
1045  if (pool->servers[i]->cs) {
1046  rad_assert(0 == 1);
1047  return;
1048  }
1049  }
1050  }
1051 
1052  if (!pool_free_init) {
1053  pthread_mutex_init(&pool_free_mutex, NULL);
1054  pool_free_init = true;
1055  }
1056 
1057  /*
1058  * Ensure only one caller at a time is freeing a pool.
1059  */
1060  pthread_mutex_lock(&pool_free_mutex);
1061 
1062  /*
1063  * Free all of the pools.
1064  */
1065  if (!pool) {
1066  while ((this = pool_list) != NULL) {
1067  pool_list = this->next;
1068  talloc_free(this->pool);
1069  talloc_free(this);
1070  }
1071  pthread_mutex_unlock(&pool_free_mutex);
1072  return;
1073  }
1074 
1075  now = time(NULL);
1076 
1077  /*
1078  * Free the oldest pool(s)
1079  */
1080  while ((this = pool_list) != NULL) {
1081  if (this->when > now) break;
1082 
1083  pool_list = this->next;
1084  talloc_free(this->pool);
1085  talloc_free(this);
1086  }
1087 
1088  /*
1089  * Add this pool to the end of the list.
1090  */
1091  for (last = &pool_list;
1092  *last != NULL;
1093  last = &((*last))->next) {
1094  /* do nothing */
1095  }
1096 
1097  *last = this = talloc(NULL, pool_list_t);
1098  if (!this) {
1099  talloc_free(pool); /* hope for the best */
1100  pthread_mutex_unlock(&pool_free_mutex);
1101  return;
1102  }
1103 
1104  this->next = NULL;
1105  this->when = now + 60;
1106  this->pool = pool;
1107  pthread_mutex_unlock(&pool_free_mutex);
1108 }
1109 #endif /* HAVE_PTHREAD_H */
1110 
1112 {
1113  /*
1114  * The structs aren't mutex protected. Refuse to destroy
1115  * the server.
1116  */
1117  if (event_loop_started && !realm_config->dynamic) {
1118  DEBUG("Must set \"dynamic = true\" in proxy.conf");
1119  return 0;
1120  }
1121 
1122  if (!rbtree_insert(home_pools_byname, pool)) {
1123  rad_assert("Internal sanity check failed" == NULL);
1124  return 0;
1125  }
1126 
1127  return 1;
1128 }
1129 
1131  CONF_SECTION *cs, home_type_t server_type, bool do_print)
1132 {
1133  char const *name2;
1134  home_pool_t *pool = NULL;
1135  char const *value;
1136  CONF_PAIR *cp;
1137  int num_home_servers;
1138  home_server_t *home;
1139 
1140  name2 = cf_section_name1(cs);
1141  if (!name2 || ((strcasecmp(name2, "server_pool") != 0) &&
1142  (strcasecmp(name2, "home_server_pool") != 0))) {
1143  cf_log_err_cs(cs,
1144  "Section is not a home_server_pool");
1145  return 0;
1146  }
1147 
1148  name2 = cf_section_name2(cs);
1149  if (!name2) {
1150  cf_log_err_cs(cs,
1151  "Server pool section is missing a name");
1152  return 0;
1153  }
1154 
1155  /*
1156  * Count the home servers and initalize them.
1157  */
1158  num_home_servers = 0;
1159  for (cp = cf_pair_find(cs, "home_server");
1160  cp != NULL;
1161  cp = cf_pair_find_next(cs, cp, "home_server")) {
1162  num_home_servers++;
1163 
1164  if (!pool_check_home_server(rc, cp, cf_pair_value(cp),
1165  server_type, &home)) {
1166  return 0;
1167  }
1168  }
1169 
1170  if (num_home_servers == 0) {
1171  cf_log_err_cs(cs,
1172  "No home servers defined in pool %s",
1173  name2);
1174  goto error;
1175  }
1176 
1177  pool = server_pool_alloc(rc, name2, HOME_POOL_FAIL_OVER, server_type,
1178  num_home_servers);
1179  pool->cs = cs;
1180 
1181 
1182  /*
1183  * Fallback servers must be defined, and must be
1184  * virtual servers.
1185  */
1186  cp = cf_pair_find(cs, "fallback");
1187  if (cp) {
1188 #ifdef WITH_COA
1189  if (server_type == HOME_TYPE_COA) {
1190  cf_log_err_cs(cs, "Home server pools of type \"coa\" cannot have a fallback virtual server");
1191  goto error;
1192  }
1193 #endif
1194 
1195  if (!pool_check_home_server(rc, cp, cf_pair_value(cp), server_type, &pool->fallback)) {
1196  goto error;
1197  }
1198 
1199  if (!pool->fallback->server) {
1200  cf_log_err_cs(cs, "Fallback home_server %s does NOT contain a virtual_server directive",
1201  pool->fallback->log_name);
1202  goto error;
1203  }
1204  }
1205 
1206  if (do_print) cf_log_info(cs, " home_server_pool %s {", name2);
1207 
1208  cp = cf_pair_find(cs, "type");
1209  if (cp) {
1210  static FR_NAME_NUMBER pool_types[] = {
1211  { "load-balance", HOME_POOL_LOAD_BALANCE },
1212 
1213  { "fail-over", HOME_POOL_FAIL_OVER },
1214  { "fail_over", HOME_POOL_FAIL_OVER },
1215 
1216  { "round-robin", HOME_POOL_LOAD_BALANCE },
1217  { "round_robin", HOME_POOL_LOAD_BALANCE },
1218 
1219  { "client-balance", HOME_POOL_CLIENT_BALANCE },
1220  { "client-port-balance", HOME_POOL_CLIENT_PORT_BALANCE },
1221  { "keyed-balance", HOME_POOL_KEYED_BALANCE },
1222  { NULL, 0 }
1223  };
1224 
1225  value = cf_pair_value(cp);
1226  if (!value) {
1227  cf_log_err_cp(cp,
1228  "No value given for type");
1229  goto error;
1230  }
1231 
1232  pool->type = fr_str2int(pool_types, value, 0);
1233  if (!pool->type) {
1234  cf_log_err_cp(cp,
1235  "Unknown type \"%s\".",
1236  value);
1237  goto error;
1238  }
1239 
1240  if (do_print) cf_log_info(cs, "\ttype = %s", value);
1241  }
1242 
1243  cp = cf_pair_find(cs, "virtual_server");
1244  if (cp) {
1245  pool->virtual_server = cf_pair_value(cp);
1246  if (!pool->virtual_server) {
1247  cf_log_err_cp(cp, "No value given for virtual_server");
1248  goto error;
1249  }
1250 
1251  if (do_print) {
1252  cf_log_info(cs, "\tvirtual_server = %s", pool->virtual_server);
1253  }
1254 
1255  if (!cf_section_sub_find_name2(rc->cs, "server", pool->virtual_server)) {
1256  cf_log_err_cp(cp, "No such server %s", pool->virtual_server);
1257  goto error;
1258  }
1259 
1260  }
1261 
1262  num_home_servers = 0;
1263  for (cp = cf_pair_find(cs, "home_server");
1264  cp != NULL;
1265  cp = cf_pair_find_next(cs, cp, "home_server")) {
1266  home_server_t myhome;
1267 
1268  value = cf_pair_value(cp);
1269 
1270  memset(&myhome, 0, sizeof(myhome));
1271  myhome.name = value;
1272  myhome.type = server_type;
1273 
1274  home = rbtree_finddata(home_servers_byname, &myhome);
1275  if (!home) {
1276  switch (server_type) {
1277  case HOME_TYPE_AUTH:
1278  case HOME_TYPE_ACCT:
1279  myhome.type = HOME_TYPE_AUTH_ACCT;
1280  home = rbtree_finddata(home_servers_byname, &myhome);
1281  break;
1282 
1283  default:
1284  break;
1285  }
1286  }
1287 
1288  if (!home) {
1289  ERROR("Failed to find home server %s", value);
1290  goto error;
1291  }
1292 
1293  if (do_print) cf_log_info(cs, "\thome_server = %s", home->name);
1294  pool->servers[num_home_servers++] = home;
1295  } /* loop over home_server's */
1296 
1297  if (pool->fallback && do_print) {
1298  cf_log_info(cs, "\tfallback = %s", pool->fallback->name);
1299  }
1300 
1301  if (!realm_pool_add(pool, cs)) goto error;
1302 
1303  if (do_print) cf_log_info(cs, " }");
1304 
1305  cf_data_add(cs, "home_server_pool", pool, NULL);
1306  (void) talloc_steal(cs, pool);
1307 
1308  rad_assert(pool->server_type != 0);
1309 
1310  return 1;
1311 
1312  error:
1313  if (do_print) cf_log_info(cs, " }");
1314  talloc_free(pool);
1315  return 0;
1316 }
1317 #endif
1318 
1320  char const *realm,
1321  char const *name, char const *secret,
1322  home_pool_type_t ldflag, home_pool_t **pool_p,
1323  home_type_t type, char const *server)
1324 {
1325 #ifdef WITH_PROXY
1326  int i, insert_point, num_home_servers;
1327  home_server_t myhome, *home;
1328  home_pool_t mypool, *pool;
1329  CONF_SECTION *subcs;
1330 #else
1331  (void) rc; /* -Wunused */
1332  (void) realm;
1333  (void) secret;
1334  (void) ldflag;
1335  (void) type;
1336  (void) server;
1337 #endif
1338 
1339  /*
1340  * LOCAL realms get sanity checked, and nothing else happens.
1341  */
1342  if (strcmp(name, "LOCAL") == 0) {
1343  if (*pool_p) {
1344  cf_log_err_cs(cs, "Realm \"%s\" cannot be both LOCAL and remote", name);
1345  return 0;
1346  }
1347  return 1;
1348  }
1349 
1350 #ifndef WITH_PROXY
1351  return 0; /* Not proxying. Can't do non-LOCAL realms */
1352 
1353 #else
1354  mypool.name = realm;
1355  mypool.server_type = type;
1356  pool = rbtree_finddata(home_pools_byname, &mypool);
1357  if (pool) {
1358  if (pool->type != ldflag) {
1359  cf_log_err_cs(cs, "Inconsistent ldflag for server pool \"%s\"", name);
1360  return 0;
1361  }
1362 
1363  if (pool->server_type != type) {
1364  cf_log_err_cs(cs, "Inconsistent home server type for server pool \"%s\"", name);
1365  return 0;
1366  }
1367  }
1368 
1369  myhome.name = name;
1370  myhome.type = type;
1371  home = rbtree_finddata(home_servers_byname, &myhome);
1372  if (home) {
1373  if (secret && (strcmp(home->secret, secret) != 0)) {
1374  cf_log_err_cs(cs, "Inconsistent shared secret for home server \"%s\"", name);
1375  return 0;
1376  }
1377 
1378  if (home->type != type) {
1379  cf_log_err_cs(cs, "Inconsistent type for home server \"%s\"", name);
1380  return 0;
1381  }
1382 
1383  /*
1384  * See if the home server is already listed
1385  * in the pool. If so, do nothing else.
1386  */
1387  if (pool) for (i = 0; i < pool->num_home_servers; i++) {
1388  if (pool->servers[i] == home) {
1389  return 1;
1390  }
1391  }
1392  }
1393 
1394  /*
1395  * If we do have a pool, check that there is room to
1396  * insert the home server we've found, or the one that we
1397  * create here.
1398  *
1399  * Note that we insert it into the LAST available
1400  * position, in order to maintain the same order as in
1401  * the configuration files.
1402  */
1403  insert_point = -1;
1404  if (pool) {
1405  for (i = pool->num_home_servers - 1; i >= 0; i--) {
1406  if (pool->servers[i]) break;
1407 
1408  if (!pool->servers[i]) {
1409  insert_point = i;
1410  }
1411  }
1412 
1413  if (insert_point < 0) {
1414  cf_log_err_cs(cs, "No room in pool to add home server \"%s\". Please update the realm configuration to use the new-style home servers and server pools.", name);
1415  return 0;
1416  }
1417  }
1418 
1419  /*
1420  * No home server, allocate one.
1421  */
1422  if (!home) {
1423  char const *p;
1424  char *q;
1425 
1426  home = talloc_zero(rc, home_server_t);
1427 
1428  home->name = name;
1429  home->type = type;
1430  home->secret = secret;
1431  home->cs = cs;
1432  home->proto = IPPROTO_UDP;
1433 
1434  p = strchr(name, ':');
1435  if (!p) {
1436  if (type == HOME_TYPE_AUTH) {
1437  home->port = PW_AUTH_UDP_PORT;
1438  } else {
1439  home->port = PW_ACCT_UDP_PORT;
1440  }
1441 
1442  p = name;
1443  q = NULL;
1444 
1445  } else if (p == name) {
1446  cf_log_err_cs(cs, "Invalid hostname %s", name);
1447  talloc_free(home);
1448  return 0;
1449 
1450  } else {
1451  unsigned long port = strtoul(p + 1, NULL, 0);
1452  if ((port == 0) || (port > 65535)) {
1453  cf_log_err_cs(cs, "Invalid port %s", p + 1);
1454  talloc_free(home);
1455  return 0;
1456  }
1457 
1458  home->port = (uint16_t)port;
1459  q = talloc_array(home, char, (p - name) + 1);
1460  memcpy(q, name, (p - name));
1461  q[p - name] = '\0';
1462  p = q;
1463  }
1464 
1465  if (!server) {
1466  if (fr_inet_hton(&home->ipaddr, AF_UNSPEC, p, false) < 0) {
1467  cf_log_err_cs(cs,
1468  "Failed looking up hostname %s.",
1469  p);
1470  talloc_free(home);
1471  return 0;
1472  }
1473  home->src_ipaddr.af = home->ipaddr.af;
1474  } else {
1475  home->ipaddr.af = AF_UNSPEC;
1476  home->server = server;
1477  }
1478  talloc_free(q);
1479 
1480  /*
1481  * Use the old-style configuration.
1482  */
1483  home->max_outstanding = 65535*16;
1484  home->zombie_period = rc->retry_delay * rc->retry_count;
1485  if (home->zombie_period < 2) home->zombie_period = 30;
1486  home->response_window.tv_sec = home->zombie_period - 1;
1487  home->response_window.tv_usec = 0;
1488 
1490 
1491  home->revive_interval = rc->dead_time;
1492 
1493  if (rbtree_finddata(home_servers_byaddr, home)) {
1494  cf_log_err_cs(cs, "Home server %s has the same IP address and/or port as another home server.", name);
1495  talloc_free(home);
1496  return 0;
1497  }
1498 
1499  if (!rbtree_insert(home_servers_byname, home)) {
1500  cf_log_err_cs(cs, "Internal error %d adding home server %s.", __LINE__, name);
1501  talloc_free(home);
1502  return 0;
1503  }
1504 
1505  if (!rbtree_insert(home_servers_byaddr, home)) {
1506  rbtree_deletebydata(home_servers_byname, home);
1507  cf_log_err_cs(cs, "Internal error %d adding home server %s.", __LINE__, name);
1508  talloc_free(home);
1509  return 0;
1510  }
1511 
1512 #ifdef WITH_STATS
1513  home->number = home_server_max_number++;
1514  if (!rbtree_insert(home_servers_bynumber, home)) {
1515  rbtree_deletebydata(home_servers_byname, home);
1516  if (home->ipaddr.af != AF_UNSPEC) {
1517  rbtree_deletebydata(home_servers_byname, home);
1518  }
1519  cf_log_err_cs(cs,
1520  "Internal error %d adding home server %s.",
1521  __LINE__, name);
1522  talloc_free(home);
1523  return 0;
1524  }
1525 #endif
1526  }
1527 
1528  /*
1529  * We now have a home server, see if we can insert it
1530  * into pre-existing pool.
1531  */
1532  if (insert_point >= 0) {
1533  rad_assert(pool != NULL);
1534  pool->servers[insert_point] = home;
1535  return 1;
1536  }
1537 
1538  rad_assert(pool == NULL);
1539  rad_assert(home != NULL);
1540 
1541  /*
1542  * Count the old-style realms of this name.
1543  */
1544  num_home_servers = 0;
1545  for (subcs = cf_section_find_next(cs, NULL, "realm");
1546  subcs != NULL;
1547  subcs = cf_section_find_next(cs, subcs, "realm")) {
1548  char const *this = cf_section_name2(subcs);
1549 
1550  if (!this || (strcmp(this, realm) != 0)) continue;
1551  num_home_servers++;
1552  }
1553 
1554  if (num_home_servers == 0) {
1555  cf_log_err_cs(cs, "Internal error counting pools for home server %s.", name);
1556  talloc_free(home);
1557  return 0;
1558  }
1559 
1560  pool = server_pool_alloc(rc, realm, ldflag, type, num_home_servers);
1561  if (!pool) {
1562  cf_log_err_cs(cs, "Out of memory");
1563  return 0;
1564  }
1565 
1566  pool->cs = cs;
1567 
1568  pool->servers[0] = home;
1569 
1570  if (!rbtree_insert(home_pools_byname, pool)) {
1571  rad_assert("Internal sanity check failed" == NULL);
1572  return 0;
1573  }
1574 
1575  *pool_p = pool;
1576 
1577  return 1;
1578 #endif
1579 }
1580 
1582 {
1583  char const *host;
1584  char const *secret = NULL;
1585  home_pool_type_t ldflag;
1586  CONF_PAIR *cp;
1587 
1588  cp = cf_pair_find(cs, "ldflag");
1589  ldflag = HOME_POOL_FAIL_OVER;
1590  if (cp) {
1591  host = cf_pair_value(cp);
1592  if (!host) {
1593  cf_log_err_cp(cp, "No value specified for ldflag");
1594  return 0;
1595  }
1596 
1597  if (strcasecmp(host, "fail_over") == 0) {
1598  cf_log_info(cs, "\tldflag = fail_over");
1599 
1600  } else if (strcasecmp(host, "round_robin") == 0) {
1601  ldflag = HOME_POOL_LOAD_BALANCE;
1602  cf_log_info(cs, "\tldflag = round_robin");
1603 
1604  } else {
1605  cf_log_err_cs(cs, "Unknown value \"%s\" for ldflag", host);
1606  return 0;
1607  }
1608  } /* else don't print it. */
1609 
1610  /*
1611  * Allow old-style if it doesn't exist, or if it exists and
1612  * it's LOCAL.
1613  */
1614  cp = cf_pair_find(cs, "authhost");
1615  if (cp) {
1616  host = cf_pair_value(cp);
1617  if (!host) {
1618  cf_log_err_cp(cp, "No value specified for authhost");
1619  return 0;
1620  }
1621 
1622  if (strcmp(host, "LOCAL") != 0) {
1623  cp = cf_pair_find(cs, "secret");
1624  if (!cp) {
1625  cf_log_err_cs(cs, "No shared secret supplied for realm: %s", r->name);
1626  return 0;
1627  }
1628 
1629  secret = cf_pair_value(cp);
1630  if (!secret) {
1631  cf_log_err_cp(cp, "No value specified for secret");
1632  return 0;
1633  }
1634  }
1635 
1636  cf_log_info(cs, "\tauthhost = %s", host);
1637 
1638  if (!old_server_add(rc, cs, r->name, host, secret, ldflag,
1639  &r->auth_pool, HOME_TYPE_AUTH, NULL)) {
1640  return 0;
1641  }
1642  }
1643 
1644  cp = cf_pair_find(cs, "accthost");
1645  if (cp) {
1646  host = cf_pair_value(cp);
1647  if (!host) {
1648  cf_log_err_cp(cp, "No value specified for accthost");
1649  return 0;
1650  }
1651 
1652  /*
1653  * Don't look for a secret again if it was found
1654  * above.
1655  */
1656  if ((strcmp(host, "LOCAL") != 0) && !secret) {
1657  cp = cf_pair_find(cs, "secret");
1658  if (!cp) {
1659  cf_log_err_cs(cs, "No shared secret supplied for realm: %s", r->name);
1660  return 0;
1661  }
1662 
1663  secret = cf_pair_value(cp);
1664  if (!secret) {
1665  cf_log_err_cp(cp, "No value specified for secret");
1666  return 0;
1667  }
1668  }
1669 
1670  cf_log_info(cs, "\taccthost = %s", host);
1671 
1672  if (!old_server_add(rc, cs, r->name, host, secret, ldflag,
1673  &r->acct_pool, HOME_TYPE_ACCT, NULL)) {
1674  return 0;
1675  }
1676  }
1677 
1678  cp = cf_pair_find(cs, "virtual_server");
1679  if (cp) {
1680  host = cf_pair_value(cp);
1681  if (!host) {
1682  cf_log_err_cp(cp, "No value specified for virtual_server");
1683  return 0;
1684  }
1685 
1686  cf_log_info(cs, "\tvirtual_server = %s", host);
1687 
1688  if (!old_server_add(rc, cs, r->name, host, "", ldflag,
1689  &r->auth_pool, HOME_TYPE_AUTH, host)) {
1690  return 0;
1691  }
1692  if (!old_server_add(rc, cs, r->name, host, "", ldflag,
1693  &r->acct_pool, HOME_TYPE_ACCT, host)) {
1694  return 0;
1695  }
1696  }
1697 
1698  if (secret) {
1699  if (rad_debug_lvl <= 2) {
1700  cf_log_info(cs, "\tsecret = <<< secret >>>");
1701  } else {
1702  cf_log_info(cs, "\tsecret = %s", secret);
1703  }
1704  }
1705 
1706  return 1;
1707 
1708 }
1709 
1710 
1711 #ifdef WITH_PROXY
1713  char const *name, home_pool_t **dest,
1714  home_type_t server_type, bool do_print)
1715 {
1716  home_pool_t mypool, *pool;
1717 
1718  mypool.name = name;
1719  mypool.server_type = server_type;
1720 
1721  pool = rbtree_finddata(home_pools_byname, &mypool);
1722  if (!pool) {
1723  CONF_SECTION *pool_cs;
1724 
1725  pool_cs = cf_section_sub_find_name2(rc->cs,
1726  "home_server_pool",
1727  name);
1728  if (!pool_cs) {
1729  pool_cs = cf_section_sub_find_name2(rc->cs,
1730  "server_pool",
1731  name);
1732  }
1733  if (!pool_cs) {
1734  cf_log_err_cs(cs, "Failed to find home_server_pool \"%s\"", name);
1735  return 0;
1736  }
1737 
1738  if (!server_pool_add(rc, pool_cs, server_type, do_print)) {
1739  return 0;
1740  }
1741 
1742  pool = rbtree_finddata(home_pools_byname, &mypool);
1743  if (!pool) {
1744  ERROR("Internal sanity check failed in add_pool_to_realm");
1745  return 0;
1746  }
1747  }
1748 
1749  if (pool->server_type != server_type) {
1750  cf_log_err_cs(cs, "Incompatible home_server_pool \"%s\" (mixed auth_pool / acct_pool)", name);
1751  return 0;
1752  }
1753 
1754  *dest = pool;
1755 
1756  return 1;
1757 }
1758 #endif
1759 
1760 
1762 {
1763  char const *name2;
1764  REALM *r = NULL;
1765  CONF_PAIR *cp;
1766 #ifdef WITH_PROXY
1767  home_pool_t *auth_pool, *acct_pool;
1768  char const *auth_pool_name, *acct_pool_name;
1769 #ifdef WITH_COA
1770  char const *coa_pool_name;
1771  home_pool_t *coa_pool;
1772 #endif
1773 #endif
1774 
1775  name2 = cf_section_name1(cs);
1776  if (!name2 || (strcasecmp(name2, "realm") != 0)) {
1777  cf_log_err_cs(cs, "Section is not a realm");
1778  return 0;
1779  }
1780 
1781  name2 = cf_section_name2(cs);
1782  if (!name2) {
1783  cf_log_err_cs(cs, "Realm section is missing the realm name");
1784  return 0;
1785  }
1786 
1787 #ifdef WITH_PROXY
1788  auth_pool = acct_pool = NULL;
1789  auth_pool_name = acct_pool_name = NULL;
1790 #ifdef WITH_COA
1791  coa_pool = NULL;
1792  coa_pool_name = NULL;
1793 #endif
1794 
1795  /*
1796  * Prefer new configuration to old one.
1797  */
1798  cp = cf_pair_find(cs, "pool");
1799  if (!cp) cp = cf_pair_find(cs, "home_server_pool");
1800  if (cp) auth_pool_name = cf_pair_value(cp);
1801  if (cp && auth_pool_name) {
1802  acct_pool_name = auth_pool_name;
1803  if (!add_pool_to_realm(rc, cs,
1804  auth_pool_name, &auth_pool,
1805  HOME_TYPE_AUTH, 1)) {
1806  return 0;
1807  }
1808  if (!add_pool_to_realm(rc, cs,
1809  auth_pool_name, &acct_pool,
1810  HOME_TYPE_ACCT, 0)) {
1811  return 0;
1812  }
1813  }
1814 
1815  cp = cf_pair_find(cs, "auth_pool");
1816  if (cp) auth_pool_name = cf_pair_value(cp);
1817  if (cp && auth_pool_name) {
1818  if (auth_pool) {
1819  cf_log_err_cs(cs, "Cannot use \"pool\" and \"auth_pool\" at the same time");
1820  return 0;
1821  }
1822  if (!add_pool_to_realm(rc, cs,
1823  auth_pool_name, &auth_pool,
1824  HOME_TYPE_AUTH, 1)) {
1825  return 0;
1826  }
1827  }
1828 
1829  cp = cf_pair_find(cs, "acct_pool");
1830  if (cp) acct_pool_name = cf_pair_value(cp);
1831  if (cp && acct_pool_name) {
1832  bool do_print = true;
1833 
1834  if (acct_pool) {
1835  cf_log_err_cs(cs, "Cannot use \"pool\" and \"acct_pool\" at the same time");
1836  return 0;
1837  }
1838 
1839  if (!auth_pool ||
1840  (auth_pool_name &&
1841  (strcmp(auth_pool_name, acct_pool_name) != 0))) {
1842  do_print = true;
1843  }
1844 
1845  if (!add_pool_to_realm(rc, cs,
1846  acct_pool_name, &acct_pool,
1847  HOME_TYPE_ACCT, do_print)) {
1848  return 0;
1849  }
1850  }
1851 
1852 #ifdef WITH_COA
1853  cp = cf_pair_find(cs, "coa_pool");
1854  if (cp) coa_pool_name = cf_pair_value(cp);
1855  if (cp && coa_pool_name) {
1856  bool do_print = true;
1857 
1858  if (!add_pool_to_realm(rc, cs,
1859  coa_pool_name, &coa_pool,
1860  HOME_TYPE_COA, do_print)) {
1861  return 0;
1862  }
1863  }
1864 #endif
1865 #endif
1866 
1867  cf_log_info(cs, " realm %s {", name2);
1868 
1869 #ifdef WITH_PROXY
1870  /*
1871  * The realm MAY already exist if it's an old-style realm.
1872  * In that case, merge the old-style realm with this one.
1873  */
1874  r = realm_find2(name2);
1875  if (r && (strcmp(r->name, name2) == 0)) {
1876  if (cf_pair_find(cs, "auth_pool") ||
1877  cf_pair_find(cs, "acct_pool")) {
1878  cf_log_err_cs(cs, "Duplicate realm \"%s\"", name2);
1879  goto error;
1880  }
1881 
1882  if (!old_realm_config(rc, cs, r)) {
1883  goto error;
1884  }
1885 
1886  cf_log_info(cs, " } # realm %s", name2);
1887  return 1;
1888  }
1889 #endif
1890 
1891  r = talloc_zero(rc, REALM);
1892  if (!r) return 0;
1893 
1894  r->name = name2;
1895  r->strip_realm = true;
1896 #ifdef WITH_PROXY
1897  r->auth_pool = auth_pool;
1898  r->acct_pool = acct_pool;
1899 #ifdef WITH_COA
1900  r->coa_pool = coa_pool;
1901 #endif
1902 
1903  if (auth_pool_name &&
1904  (auth_pool_name == acct_pool_name)) { /* yes, ptr comparison */
1905  cf_log_info(cs, "\tpool = %s", auth_pool_name);
1906  } else {
1907  if (auth_pool_name) cf_log_info(cs, "\tauth_pool = %s", auth_pool_name);
1908  if (acct_pool_name) cf_log_info(cs, "\tacct_pool = %s", acct_pool_name);
1909 #ifdef WITH_COA
1910  if (coa_pool_name) cf_log_info(cs, "\tcoa_pool = %s", coa_pool_name);
1911 #endif
1912  }
1913 #endif
1914 
1915  cp = cf_pair_find(cs, "nostrip");
1916  if (cp && (cf_pair_value(cp) == NULL)) {
1917  r->strip_realm = false;
1918  cf_log_info(cs, "\tnostrip");
1919  }
1920 
1921  /*
1922  * We're a new-style realm. Complain if we see the old
1923  * directives.
1924  */
1925  if (r->auth_pool || r->acct_pool) {
1926  if (((cp = cf_pair_find(cs, "authhost")) != NULL) ||
1927  ((cp = cf_pair_find(cs, "accthost")) != NULL) ||
1928  ((cp = cf_pair_find(cs, "secret")) != NULL) ||
1929  ((cp = cf_pair_find(cs, "ldflag")) != NULL)) {
1930  WARN("Ignoring old-style configuration entry \"%s\" in realm \"%s\"", cf_pair_attr(cp), r->name);
1931  }
1932 
1933 
1934  /*
1935  * The realm MAY be an old-style realm, as there
1936  * was no auth_pool or acct_pool. Double-check
1937  * it, just to be safe.
1938  */
1939  } else if (!old_realm_config(rc, cs, r)) {
1940  goto error;
1941  }
1942 
1943  if (!realm_realm_add(r, cs)) {
1944  goto error;
1945  }
1946 
1947  cf_log_info(cs, " }");
1948 
1949  return 1;
1950 
1951  error:
1952  cf_log_info(cs, " } # realm %s", name2);
1953  return 0;
1954 }
1955 
1956 #ifdef HAVE_REGEX
1958 #else
1960 #endif
1961 {
1962  /*
1963  * The structs aren't mutex protected. Refuse to destroy
1964  * the server.
1965  */
1966  if (event_loop_started && !realm_config->dynamic) {
1967  DEBUG("Must set \"dynamic = true\" in proxy.conf");
1968  return 0;
1969  }
1970 
1971 #ifdef HAVE_REGEX
1972  /*
1973  * It's a regex. Sanity check it, and add it to a
1974  * separate list.
1975  */
1976  if (r->name[0] == '~') {
1977  ssize_t slen;
1978  realm_regex_t *rr, **last;
1979 
1980  rr = talloc(r, realm_regex_t);
1981 
1982  /*
1983  * Include substring matches.
1984  */
1985  slen = regex_compile(rr, &rr->preg, r->name + 1, strlen(r->name) - 1, true, false, false, false);
1986  if (slen <= 0) {
1987  char *spaces, *text;
1988 
1989  fr_canonicalize_error(r, &spaces, &text, slen, r->name + 1);
1990 
1991  cf_log_err_cs(cs, "Invalid regular expression:");
1992  cf_log_err_cs(cs, "%s", text);
1993  cf_log_err_cs(cs, "%s^ %s", spaces, fr_strerror());
1994 
1995  talloc_free(spaces);
1996  talloc_free(text);
1997  talloc_free(rr);
1998 
1999  return 0;
2000  }
2001 
2002  last = &realms_regex;
2003  while (*last) last = &((*last)->next); /* O(N^2)... sue me. */
2004 
2005  rr->realm = r;
2006  rr->next = NULL;
2007 
2008  *last = rr;
2009  return 1;
2010  }
2011 #endif
2012 
2013  if (!rbtree_insert(realms_byname, r)) {
2014  rad_assert("Internal sanity check failed" == NULL);
2015  return 0;
2016  }
2017 
2018  return 1;
2019 }
2020 
2021 #ifdef WITH_COA
2022 
2023 static int pool_peek_type(CONF_SECTION *config, CONF_SECTION *cs)
2024 {
2025  int home;
2026  char const *name, *type;
2027  CONF_PAIR *cp;
2028  CONF_SECTION *server_cs;
2029 
2030  cp = cf_pair_find(cs, "home_server");
2031  if (!cp) {
2032  cf_log_err_cs(cs, "Pool does not contain a \"home_server\" entry");
2033  return HOME_TYPE_INVALID;
2034  }
2035 
2036  name = cf_pair_value(cp);
2037  if (!name) {
2038  cf_log_err_cp(cp, "home_server entry does not reference a home server");
2039  return HOME_TYPE_INVALID;
2040  }
2041 
2042  server_cs = cf_section_sub_find_name2(config, "home_server", name);
2043  if (!server_cs) {
2044  cf_log_err_cp(cp, "home_server \"%s\" does not exist", name);
2045  return HOME_TYPE_INVALID;
2046  }
2047 
2048  cp = cf_pair_find(server_cs, "type");
2049  if (!cp) {
2050  cf_log_err_cs(server_cs, "home_server %s does not contain a \"type\" entry", name);
2051  return HOME_TYPE_INVALID;
2052  }
2053 
2054  type = cf_pair_value(cp);
2055  if (!type) {
2056  cf_log_err_cs(server_cs, "home_server %s contains an empty \"type\" entry", name);
2057  return HOME_TYPE_INVALID;
2058  }
2059 
2060  home = fr_str2int(home_server_types, type, HOME_TYPE_INVALID);
2061  if (home == HOME_TYPE_INVALID) {
2062  cf_log_err_cs(server_cs, "home_server %s contains an invalid \"type\" entry of value \"%s\"", name, type);
2063  return HOME_TYPE_INVALID;
2064  }
2065 
2066  return home; /* 'cause we miss it so much */
2067 }
2068 #endif
2069 
2071 {
2072  CONF_SECTION *cs;
2073  int flags = 0;
2074 #ifdef WITH_PROXY
2075  CONF_SECTION *server_cs;
2076 #endif
2077  realm_config_t *rc;
2078 
2079  if (event_loop_started) return 1;
2080 
2081  rc = talloc_zero(NULL, realm_config_t);
2082  rc->cs = config;
2083 
2084 #ifdef WITH_PROXY
2085  cs = cf_subsection_find_next(config, NULL, "proxy");
2086  if (cs) {
2087  if (cf_section_parse(cs, rc, proxy_config) < 0) {
2088  ERROR("Failed parsing proxy section");
2089  goto error;
2090  }
2091  } else {
2092  rc->dead_time = DEAD_TIME;
2093  rc->retry_count = RETRY_COUNT;
2094  rc->retry_delay = RETRY_DELAY;
2095  rc->fallback = false;
2096  rc->dynamic = false;
2097  rc->wake_all_if_all_dead= 0;
2098  }
2099 
2100  if (rc->dynamic) {
2101  flags = RBTREE_FLAG_LOCK;
2102  }
2103 
2104  home_servers_byaddr = rbtree_create(NULL, home_server_addr_cmp, home_server_free, flags);
2105  if (!home_servers_byaddr) goto error;
2106 
2107  home_servers_byname = rbtree_create(NULL, home_server_name_cmp, NULL, flags);
2108  if (!home_servers_byname) goto error;
2109 
2110 #ifdef WITH_STATS
2111  home_servers_bynumber = rbtree_create(NULL, home_server_number_cmp, NULL, flags);
2112  if (!home_servers_bynumber) goto error;
2113 #endif
2114 
2115  home_pools_byname = rbtree_create(NULL, home_pool_name_cmp, NULL, flags);
2116  if (!home_pools_byname) goto error;
2117 
2118  for (cs = cf_subsection_find_next(config, NULL, "home_server");
2119  cs != NULL;
2120  cs = cf_subsection_find_next(config, cs, "home_server")) {
2121  home_server_t *home;
2122 
2123  home = home_server_afrom_cs(rc, rc, cs);
2124  if (!home) goto error;
2125  if (!realm_home_server_add(home)) goto error;
2126  }
2127 
2128  /*
2129  * Loop over virtual servers to find home servers which
2130  * are defined in them.
2131  */
2132  for (server_cs = cf_subsection_find_next(config, NULL, "server");
2133  server_cs != NULL;
2134  server_cs = cf_subsection_find_next(config, server_cs, "server")) {
2135  for (cs = cf_subsection_find_next(server_cs, NULL, "home_server");
2136  cs != NULL;
2137  cs = cf_subsection_find_next(server_cs, cs, "home_server")) {
2138  home_server_t *home;
2139 
2140  home = home_server_afrom_cs(rc, rc, cs);
2141  if (!home) goto error;
2142  if (!realm_home_server_add(home)) goto error;
2143  }
2144  }
2145 #endif
2146 
2147  /*
2148  * Now create the realms, which point to the home servers
2149  * and home server pools.
2150  */
2151  realms_byname = rbtree_create(NULL, realm_name_cmp, NULL, flags);
2152  if (!realms_byname) goto error;
2153 
2154  for (cs = cf_subsection_find_next(config, NULL, "realm");
2155  cs != NULL;
2156  cs = cf_subsection_find_next(config, cs, "realm")) {
2157  if (!realm_add(rc, cs)) {
2158  error:
2159  realms_free();
2160  /*
2161  * Must be called after realms_free as home_servers
2162  * parented by rc are in trees freed by realms_free()
2163  */
2164  talloc_free(rc);
2165  return 0;
2166  }
2167  }
2168 
2169 #ifdef WITH_COA
2170  /*
2171  * CoA pools aren't necessarily tied to realms.
2172  */
2173  for (cs = cf_subsection_find_next(config, NULL, "home_server_pool");
2174  cs != NULL;
2175  cs = cf_subsection_find_next(config, cs, "home_server_pool")) {
2176  int type;
2177 
2178  /*
2179  * Pool was already loaded.
2180  */
2181  if (cf_data_find(cs, "home_server_pool")) continue;
2182 
2183  type = pool_peek_type(config, cs);
2184  if (type == HOME_TYPE_INVALID) goto error;
2185  if (!server_pool_add(rc, cs, type, true)) goto error;
2186  }
2187 #endif
2188 
2189 #ifdef WITH_PROXY
2190  xlat_register(NULL, "home_server", xlat_home_server, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN);
2191  xlat_register(NULL, "home_server_pool", xlat_server_pool, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN);
2192 #endif
2193 
2194  realm_config = rc;
2195  return 1;
2196 }
2197 
2198 /*
2199  * Find a realm where "name" might be the regex.
2200  */
2201 REALM *realm_find2(char const *name)
2202 {
2203  REALM myrealm;
2204  REALM *realm;
2205 
2206  if (!name) name = "NULL";
2207 
2208  myrealm.name = name;
2209  realm = rbtree_finddata(realms_byname, &myrealm);
2210  if (realm) return realm;
2211 
2212 #ifdef HAVE_REGEX
2213  if (realms_regex) {
2214  realm_regex_t *this;
2215 
2216  for (this = realms_regex; this != NULL; this = this->next) {
2217  if (strcmp(this->realm->name, name) == 0) {
2218  return this->realm;
2219  }
2220  }
2221  }
2222 #endif
2223 
2224  /*
2225  * Couldn't find a realm. Look for DEFAULT.
2226  */
2227  myrealm.name = "DEFAULT";
2228  return rbtree_finddata(realms_byname, &myrealm);
2229 }
2230 
2231 
2232 /*
2233  * Find a realm in the REALM list.
2234  */
2235 REALM *realm_find(char const *name)
2236 {
2237  REALM myrealm;
2238  REALM *realm;
2239 
2240  if (!name) name = "NULL";
2241 
2242  myrealm.name = name;
2243  realm = rbtree_finddata(realms_byname, &myrealm);
2244  if (realm) return realm;
2245 
2246 #ifdef HAVE_REGEX
2247  if (realms_regex) {
2248  realm_regex_t *this;
2249 
2250  for (this = realms_regex;
2251  this != NULL;
2252  this = this->next) {
2253  int compare;
2254 
2255  compare = regex_exec(this->preg, name, strlen(name), NULL, NULL);
2256  if (compare < 0) {
2257  ERROR("Failed performing realm comparison: %s", fr_strerror());
2258  return NULL;
2259  }
2260  if (compare == 1) return this->realm;
2261  }
2262  }
2263 #endif
2264 
2265  /*
2266  * Couldn't find a realm. Look for DEFAULT.
2267  */
2268  myrealm.name = "DEFAULT";
2269  return rbtree_finddata(realms_byname, &myrealm);
2270 }
2271 
2272 
2273 #ifdef WITH_PROXY
2274 
2275 /*
2276  * Allocate the proxy list if it doesn't already exist, and copy request
2277  * VPs into it. Setup src/dst IP addresses based on home server, and
2278  * calculate and add the message-authenticator.
2279  *
2280  * This is a distinct function from home_server_ldb, as not all home_server_t
2281  * lookups result in the *CURRENT* request being proxied,
2282  * as in rlm_replicate, and this may trigger asserts elsewhere in the
2283  * server.
2284  */
2286 {
2287 
2288  /*
2289  * Allocate the proxy packet, only if it wasn't
2290  * already allocated by a module. This check is
2291  * mainly to support the proxying of EAP-TTLS and
2292  * EAP-PEAP tunneled requests.
2293  *
2294  * In those cases, the EAP module creates a
2295  * "fake" request, and recursively passes it
2296  * through the authentication stage of the
2297  * server. The module then checks if the request
2298  * was supposed to be proxied, and if so, creates
2299  * a proxy packet from the TUNNELED request, and
2300  * not from the EAP request outside of the
2301  * tunnel.
2302  *
2303  * The proxy then works like normal, except that
2304  * the response packet is "eaten" by the EAP
2305  * module, and encapsulated into an EAP packet.
2306  */
2307  if (!request->proxy) {
2308  request->proxy = fr_radius_alloc(request, true);
2309  if (!request->proxy) {
2310  ERROR("no memory");
2311  fr_exit(1);
2312  }
2313 
2314  /*
2315  * Copy the request, then look up name
2316  * and plain-text password in the copy.
2317  *
2318  * Note that the User-Name attribute is
2319  * the *original* as sent over by the
2320  * client. The Stripped-User-Name
2321  * attribute is the one hacked through
2322  * the 'hints' file.
2323  */
2324  request->proxy->vps = fr_pair_list_copy(request->proxy,
2325  request->packet->vps);
2326  }
2327 
2328  /*
2329  * Update the various fields as appropriate.
2330  */
2331  request->proxy->src_ipaddr = home->src_ipaddr;
2332  request->proxy->src_port = 0;
2333  request->proxy->dst_ipaddr = home->ipaddr;
2334  request->proxy->dst_port = home->port;
2335 #ifdef WITH_TCP
2336  request->proxy->proto = home->proto;
2337 #endif
2338  request->home_server = home;
2339 
2340  /*
2341  * Access-Requests have a Message-Authenticator added,
2342  * unless one already exists.
2343  */
2344  if ((request->packet->code == PW_CODE_ACCESS_REQUEST) &&
2345  !fr_pair_find_by_num(request->proxy->vps, 0, PW_MESSAGE_AUTHENTICATOR, TAG_ANY)) {
2346  fr_pair_make(request->proxy, &request->proxy->vps,
2347  "Message-Authenticator", "0x00",
2348  T_OP_SET);
2349  }
2350 }
2351 
2352 home_server_t *home_server_ldb(char const *realmname,
2353  home_pool_t *pool, REQUEST *request)
2354 {
2355  int start;
2356  int count;
2357  home_server_t *found = NULL;
2358  home_server_t *zombie = NULL;
2359  VALUE_PAIR *vp;
2360  uint32_t hash;
2361 
2362  /*
2363  * Determine how to pick choose the home server.
2364  */
2365  switch (pool->type) {
2366 
2367 
2368  /*
2369  * For load-balancing by client IP address, we
2370  * pick a home server by hashing the client IP.
2371  *
2372  * This isn't as even a load distribution as
2373  * tracking the State attribute, but it's better
2374  * than nothing.
2375  */
2377  switch (request->packet->src_ipaddr.af) {
2378  case AF_INET:
2379  hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip4addr,
2380  sizeof(request->packet->src_ipaddr.ipaddr.ip4addr));
2381  break;
2382 
2383  case AF_INET6:
2384  hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip6addr,
2385  sizeof(request->packet->src_ipaddr.ipaddr.ip6addr));
2386  break;
2387 
2388  default:
2389  hash = 0;
2390  break;
2391  }
2392  start = hash % pool->num_home_servers;
2393  break;
2394 
2396  switch (request->packet->src_ipaddr.af) {
2397  case AF_INET:
2398  hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip4addr,
2399  sizeof(request->packet->src_ipaddr.ipaddr.ip4addr));
2400  break;
2401 
2402  case AF_INET6:
2403  hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip6addr,
2404  sizeof(request->packet->src_ipaddr.ipaddr.ip6addr));
2405  break;
2406 
2407  default:
2408  hash = 0;
2409  break;
2410  }
2411  fr_hash_update(&request->packet->src_port,
2412  sizeof(request->packet->src_port), hash);
2413  start = hash % pool->num_home_servers;
2414  break;
2415 
2417  if ((vp = fr_pair_find_by_num(request->config, 0, PW_LOAD_BALANCE_KEY, TAG_ANY)) != NULL) {
2418  hash = fr_hash(vp->vp_strvalue, vp->vp_length);
2419  start = hash % pool->num_home_servers;
2420  break;
2421  }
2422  /* FALL-THROUGH */
2423 
2425  case HOME_POOL_FAIL_OVER:
2426  start = 0;
2427  break;
2428 
2429  default: /* this shouldn't happen... */
2430  start = 0;
2431  break;
2432 
2433  }
2434 
2435  /*
2436  * Starting with the home server we chose, loop through
2437  * all home servers. If the current one is dead, skip
2438  * it. If it is too busy, skip it.
2439  *
2440  * Otherwise, use it.
2441  */
2442  for (count = 0; count < pool->num_home_servers; count++) {
2443  home_server_t *home = pool->servers[(start + count) % pool->num_home_servers];
2444 
2445  if (!home) continue;
2446 
2447  /*
2448  * Skip dead home servers.
2449  *
2450  * Home servers that are unknown, alive, or zombie
2451  * are used for proxying.
2452  */
2453  if (home->state == HOME_STATE_IS_DEAD) {
2454  continue;
2455  }
2456 
2457  /*
2458  * This home server is too busy. Choose another one.
2459  */
2460  if (home->currently_outstanding >= home->max_outstanding) {
2461  continue;
2462  }
2463 
2464 #ifdef WITH_DETAIL
2465  /*
2466  * We read the packet from a detail file, AND it
2467  * came from this server. Don't re-proxy it
2468  * there.
2469  */
2470  if ((request->listener->type == RAD_LISTEN_DETAIL) &&
2471  (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) &&
2472  (fr_ipaddr_cmp(&home->ipaddr, &request->packet->src_ipaddr) == 0)) {
2473  continue;
2474  }
2475 #endif
2476 
2477  /*
2478  * Default virtual: ignore homes tied to a
2479  * virtual.
2480  */
2481  if (!request->server && home->parent_server) {
2482  continue;
2483  }
2484 
2485  /*
2486  * A virtual AND home is tied to virtual,
2487  * ignore ones which don't match.
2488  */
2489  if (request->server && home->parent_server &&
2490  strcmp(request->server, home->parent_server) != 0) {
2491  continue;
2492  }
2493 
2494  /*
2495  * Allow request->server && !home->parent_server
2496  *
2497  * i.e. virtuals can proxy to globally defined
2498  * homes.
2499  */
2500 
2501  /*
2502  * It's zombie, so we remember the first zombie
2503  * we find, but we don't mark it as a "live"
2504  * server.
2505  */
2506  if (home->state == HOME_STATE_ZOMBIE) {
2507  if (!zombie) zombie = home;
2508  continue;
2509  }
2510 
2511  /*
2512  * We've found the first "live" one. Use that.
2513  */
2514  if (pool->type != HOME_POOL_LOAD_BALANCE) {
2515  found = home;
2516  break;
2517  }
2518 
2519  /*
2520  * Otherwise we're doing some kind of load balancing.
2521  * If we haven't found one yet, pick this one.
2522  */
2523  if (!found) {
2524  found = home;
2525  continue;
2526  }
2527 
2528  RDEBUG3("PROXY %s %d\t%s %d",
2529  found->log_name, found->currently_outstanding,
2530  home->log_name, home->currently_outstanding);
2531 
2532  /*
2533  * Prefer this server if it's less busy than the
2534  * one we had previously found.
2535  */
2536  if (home->currently_outstanding < found->currently_outstanding) {
2537  RDEBUG3("PROXY Choosing %s: It's less busy than %s",
2538  home->log_name, found->log_name);
2539  found = home;
2540  continue;
2541  }
2542 
2543  /*
2544  * Ignore servers which are busier than the one
2545  * we found.
2546  */
2547  if (home->currently_outstanding > found->currently_outstanding) {
2548  RDEBUG3("PROXY Skipping %s: It's busier than %s",
2549  home->log_name, found->log_name);
2550  continue;
2551  }
2552 
2553  /*
2554  * From the list of servers which have the same
2555  * load, choose one at random.
2556  */
2557  if (((count + 1) * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
2558  found = home;
2559  }
2560  } /* loop over the home servers */
2561 
2562  /*
2563  * We have no live servers, BUT we have a zombie. Use
2564  * the zombie as a last resort.
2565  */
2566  if (!found && zombie) {
2567  found = zombie;
2568  zombie = NULL;
2569  }
2570 
2571  /*
2572  * There's a fallback if they're all dead.
2573  */
2574  if (!found && pool->fallback) {
2575  found = pool->fallback;
2576 
2577  WARN("Home server pool %s failing over to fallback %s",
2578  pool->name, found->server);
2579  if (pool->in_fallback) goto update_and_return;
2580 
2581  pool->in_fallback = true;
2582 
2583  /*
2584  * Run the trigger once an hour saying that
2585  * they're all dead.
2586  */
2587  if ((pool->time_all_dead + 3600) < request->timestamp.tv_sec) {
2588  pool->time_all_dead = request->timestamp.tv_sec;
2589  exec_trigger(request, pool->cs, "home_server_pool.fallback", false);
2590  }
2591  }
2592 
2593  if (found) {
2594  update_and_return:
2595  if ((found != pool->fallback) && pool->in_fallback) {
2596  pool->in_fallback = false;
2597  exec_trigger(request, pool->cs, "home_server_pool.normal", false);
2598  }
2599 
2600  return found;
2601  }
2602 
2603  /*
2604  * No live match found, and no fallback to the "DEFAULT"
2605  * realm. We fix this by blindly marking all servers as
2606  * "live". But only do it for ones that don't support
2607  * "pings", as they will be marked live when they
2608  * actually are live.
2609  */
2610  if (!realm_config->fallback &&
2611  realm_config->wake_all_if_all_dead) {
2612  for (count = 0; count < pool->num_home_servers; count++) {
2613  home_server_t *home = pool->servers[count];
2614 
2615  if (!home) continue;
2616 
2617  if ((home->state == HOME_STATE_IS_DEAD) &&
2618  (home->ping_check == HOME_PING_CHECK_NONE)) {
2619  home->state = HOME_STATE_ALIVE;
2620  home->response_timeouts = 0;
2621  if (!found) found = home;
2622  }
2623  }
2624 
2625  if (found) goto update_and_return;
2626  }
2627 
2628  /*
2629  * Still nothing. Look up the DEFAULT realm, but only
2630  * if we weren't looking up the NULL or DEFAULT realms.
2631  */
2632  if (realm_config->fallback &&
2633  realmname &&
2634  (strcmp(realmname, "NULL") != 0) &&
2635  (strcmp(realmname, "DEFAULT") != 0)) {
2636  REALM *rd = realm_find("DEFAULT");
2637 
2638  if (!rd) return NULL;
2639 
2640  pool = NULL;
2641  if (request->packet->code == PW_CODE_ACCESS_REQUEST) {
2642  pool = rd->auth_pool;
2643 
2644  } else if (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) {
2645  pool = rd->acct_pool;
2646  }
2647  if (!pool) return NULL;
2648 
2649  RDEBUG2("PROXY - realm %s has no live home servers. Falling back to the DEFAULT realm.", realmname);
2650  return home_server_ldb(rd->name, pool, request);
2651  }
2652 
2653  /*
2654  * Still haven't found anything. Oh well.
2655  */
2656  return NULL;
2657 }
2658 
2659 
2660 home_server_t *home_server_find(fr_ipaddr_t *ipaddr, uint16_t port, int proto)
2661 {
2662  home_server_t myhome;
2663 
2664  memset(&myhome, 0, sizeof(myhome));
2665  myhome.ipaddr = *ipaddr;
2666  myhome.src_ipaddr.af = ipaddr->af;
2667  myhome.port = port;
2668 #ifdef WITH_TCP
2669  myhome.proto = proto;
2670 #else
2671  myhome.proto = IPPROTO_UDP;
2672 #endif
2673  myhome.server = NULL; /* we're not called for internal proxying */
2674 
2675  return rbtree_finddata(home_servers_byaddr, &myhome);
2676 }
2677 
2678 #ifdef WITH_COA
2679 home_server_t *home_server_byname(char const *name, int type)
2680 {
2681  home_server_t myhome;
2682 
2683  memset(&myhome, 0, sizeof(myhome));
2684  myhome.type = type;
2685  myhome.name = name;
2686 
2687  return rbtree_finddata(home_servers_byname, &myhome);
2688 }
2689 #endif
2690 
2691 #ifdef WITH_STATS
2693 {
2694  home_server_t myhome;
2695 
2696  memset(&myhome, 0, sizeof(myhome));
2697  myhome.number = number;
2698  myhome.server = NULL; /* we're not called for internal proxying */
2699 
2700  return rbtree_finddata(home_servers_bynumber, &myhome);
2701 }
2702 #endif
2703 
2704 home_pool_t *home_pool_byname(char const *name, int type)
2705 {
2706  home_pool_t mypool;
2707 
2708  memset(&mypool, 0, sizeof(mypool));
2709  mypool.name = name;
2710  mypool.server_type = type;
2711  return rbtree_finddata(home_pools_byname, &mypool);
2712 }
2713 
2714 #endif
CONF_SECTION * cs
Definition: realms.c:56
home_server_t * servers[1]
Definition: realms.h:174
char const * name
Name the server may be referenced by for querying stats or when specifying home servers for a pool...
Definition: realms.h:71
static int pool_peek_type(CONF_SECTION *config, CONF_SECTION *cs)
Definition: realms.c:2023
static int home_server_number_cmp(void const *one, void const *two)
Definition: realms.c:168
fr_ipaddr_t src_ipaddr
Resolved version of src_ipaddr_str.
Definition: realms.h:87
#define pthread_mutex_init(_x, _y)
Definition: rlm_eap.h:75
128 Bit IPv6 Address.
Definition: radius.h:40
VALUE_PAIR * config
VALUE_PAIR (s) used to set per request parameters for modules and the server core at runtime...
Definition: radiusd.h:227
char const * ping_user_name
Definition: realms.h:119
void rbtree_free(rbtree_t *tree)
Definition: rbtree.c:84
bool wake_all_if_all_dead
Definition: realms.c:62
static rbtree_t * home_servers_byname
Definition: realms.c:84
FR_NAME_NUMBER const fr_net_ip_proto_table[]
Strings for L4 protocols.
Definition: net.c:30
int xlat_register(void *mod_inst, char const *name, xlat_func_t func, xlat_escape_t escape, xlat_instantiate_t instantiate, size_t inst_size, size_t buf_len)
Register an xlat function.
Definition: xlat.c:717
static size_t CC_HINT(nonnull)
Definition: realms.c:189
Time value (struct timeval), only for config items.
Definition: radius.h:55
Main server configuration.
Definition: radiusd.h:108
uint32_t ping_interval
Definition: realms.h:122
RAD_LISTEN_TYPE type
Definition: listen.h:76
char const * ping_check_str
Definition: realms.h:115
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
int in_fallback
Definition: realms.h:170
fr_socket_limit_t limit
Definition: realms.h:93
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 fr_hash(void const *, size_t)
Definition: hash.c:727
int fr_inet_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
Wrappers for IPv4/IPv6 host to IP address lookup.
Definition: inet.c:127
char const * ping_user_password
Definition: realms.h:120
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: radius.c:1621
void home_server_update_request(home_server_t *home, REQUEST *request)
Definition: realms.c:2285
fr_ipaddr_t src_ipaddr
Src IP address of packet.
Definition: libradius.h:149
static CONF_PARSER home_server_coa[]
Definition: realms.c:294
int fr_is_inaddr_any(fr_ipaddr_t *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
Definition: packet.c:91
WiMAX IPv4 or IPv6 address depending on length.
Definition: radius.h:46
static char const * name
home_type_t server_type
Definition: realms.h:164
#define RETRY_COUNT
Definition: radiusd.h:327
uint32_t coa_mrd
Definition: realms.h:134
void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp)
Add a configuration pair to a section.
Definition: conffile.c:612
#define UNUSED
Definition: libradius.h:134
uint32_t retry_delay
Definition: realms.c:59
static int pool_check_home_server(UNUSED realm_config_t *rc, CONF_PAIR *cp, char const *name, home_type_t server_type, home_server_t **phome)
Definition: realms.c:970
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
CONF_SECTION * cs
Definition: realms.h:129
uint32_t dead_time
Definition: realms.c:57
uint32_t num_pings_to_alive
Definition: realms.h:123
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition: missing.c:538
static rbtree_t * home_servers_byaddr
Definition: realms.c:83
void void void cf_log_err_cp(CONF_PAIR const *cp, char const *fmt,...) CC_HINT(format(printf
static rbtree_t * realms_byname
Definition: realms.c:36
char * fr_inet_ntop_prefix(char out[FR_IPADDR_PREFIX_STRLEN], size_t outlen, fr_ipaddr_t *addr)
Print a fr_ipaddr_t as a CIDR style network prefix.
Definition: inet.c:762
home_pool_t * auth_pool
Definition: realms.h:183
Definition: realms.h:178
rad_listen_t * listener
The listener that received the request.
Definition: radiusd.h:218
#define PW_TYPE_SECRET
Only print value if debug level >= 3.
Definition: conffile.h:202
void * rbtree_finddata(rbtree_t *tree, void const *data)
Find the user data.
Definition: rbtree.c:537
Definition: token.h:46
int realms_init(CONF_SECTION *config)
Definition: realms.c:2070
home_server_t * home_server_bynumber(int number)
Definition: realms.c:2692
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition: conffile.h:222
#define XLAT_DEFAULT_BUF_LEN
Definition: xlat.h:89
home_server_t * home_server_ldb(char const *realmname, home_pool_t *pool, REQUEST *request)
Definition: realms.c:2352
#define DEAD_TIME
Definition: radiusd.h:328
home_pool_type_t
Definition: realms.h:150
uint32_t max_connections
Definition: realms.h:60
uint16_t dst_port
DST Port of packet.
Definition: libradius.h:152
uint16_t src_port
Src port of packet.
Definition: libradius.h:151
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
Definition: libradius.h:150
int realm_pool_add(home_pool_t *pool, UNUSED CONF_SECTION *cs)
Definition: realms.c:1111
char const * type_str
String representation of type.
Definition: realms.h:81
#define PW_TYPE_SUBSECTION
Definition: conffile.h:188
home_type_t
Definition: realms.h:34
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
CONF_PAIR * cf_pair_find(CONF_SECTION const *, char const *name)
Definition: conffile.c:3478
char const * cf_pair_value(CONF_PAIR const *pair)
Definition: conffile.c:3506
CONF_SECTION * cs
Definition: realms.h:165
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:124
uint32_t coa_irt
Definition: realms.h:131
static char const * proto
Definition: radclient.c:63
Authentication and accounting server.
Definition: realms.h:38
uint32_t fr_hash_update(void const *data, size_t size, uint32_t hash)
Definition: hash.c:761
uint32_t response_timeouts
Definition: realms.h:101
RADIUS_PACKET * proxy
Outgoing request to proxy server.
Definition: radiusd.h:237
static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, char const *realm, char const *name, char const *secret, home_pool_type_t ldflag, home_pool_t **pool_p, home_type_t type, char const *server)
Definition: realms.c:1319
char const * server
For internal proxying.
Definition: realms.h:75
#define FR_TIMEVAL_BOUND_CHECK(_name, _var, _op, _bound_sec, _bound_usec)
Definition: conffile.h:224
static home_pool_t * server_pool_alloc(realm_config_t *rc, char const *name, home_pool_type_t type, home_type_t server_type, int num_home_servers)
Definition: realms.c:944
int af
Address family.
Definition: inet.h:42
#define rad_assert(expr)
Definition: rad_assert.h:38
uint32_t ping_timeout
Definition: realms.h:126
RFC2865 - Access-Request.
Definition: radius.h:92
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
Definition: token.c:451
static void null_free(UNUSED void *data)
Definition: realms.c:355
#define pthread_mutex_unlock(_x)
Definition: rlm_eap.h:78
static int home_server_name_cmp(void const *one, void const *two)
Definition: realms.c:128
VALUE_PAIR * fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
Copy a pairlist.
Definition: pair.c:1394
home_pool_t * home_pool
For dynamic failover.
Definition: radiusd.h:241
#define PW_COA_UDP_PORT
Definition: radius.h:120
char const * cf_pair_attr(CONF_PAIR const *pair)
Definition: conffile.c:3497
#define DEBUG(fmt,...)
Definition: log.h:175
CONF_SECTION * cf_section_dup(CONF_SECTION *parent, CONF_SECTION const *cs, char const *name1, char const *name2, bool copy_meta)
Duplicate a configuration section.
Definition: conffile.c:697
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
bool strip_realm
Definition: realms.h:181
REALM * realm_find2(char const *name)
Definition: realms.c:2201
#define PW_RADIUS_TLS_PORT
Definition: radius.h:119
uint32_t max_request_time
How long a request can be processed for before timing out.
Definition: radiusd.h:132
home_pool_t * coa_pool
Definition: realms.h:186
void realm_home_server_sanitize(home_server_t *home, CONF_SECTION *cs)
Definition: realms.c:362
void void void void cf_log_info(CONF_SECTION const *cs, char const *fmt,...) CC_HINT(format(printf
CONF_SECTION * cf_subsection_find_next(CONF_SECTION const *section, CONF_SECTION const *subsection, char const *name1)
Definition: conffile.c:3799
static char spaces[]
Definition: proto.c:28
RFC2866 - Accounting-Request.
Definition: radius.h:95
#define STRINGIFY(x)
Definition: build.h:34
CONF_SECTION * cf_item_parent(CONF_ITEM const *ci)
Definition: conffile.c:3896
RADIUS_PACKET * fr_radius_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new RADIUS_PACKET.
Definition: radius.c:1651
int cf_section_parse(CONF_SECTION *, void *base, CONF_PARSER const *variables)
Parse a configuration section into user-supplied variables.
Definition: conffile.c:2234
static void home_server_free(void *data)
Definition: realms.c:121
union fr_ipaddr_t::@1 ipaddr
static CONF_PARSER limit_config[]
Definition: realms.c:285
unsigned int code
Packet code (type).
Definition: libradius.h:155
static int home_pool_name_cmp(void const *one, void const *two)
Definition: realms.c:177
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition: conffile.c:224
REALM * realm_find(char const *name)
Definition: realms.c:2235
home_server_t * home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SECTION *cs)
Alloc a new home server defined by a CONF_SECTION.
Definition: realms.c:569
CONF_SECTION * cf_section_find_next(CONF_SECTION const *section, CONF_SECTION const *subsection, char const *name1)
Definition: conffile.c:3836
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
void rad_const_free(void const *ptr)
Definition: util.c:424
static int home_server_addr_cmp(void const *one, void const *two)
Definition: realms.c:139
void void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt,...) CC_HINT(format(printf
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *, CONF_PAIR const *, char const *name)
Find a pair with a name matching attr, after specified pair.
Definition: conffile.c:3673
int cf_data_add(CONF_SECTION *, char const *, void *, void(*)(void *))
Definition: conffile.c:4018
char const * proto_str
String representation of protocol.
Definition: realms.h:90
A truth value.
Definition: radius.h:56
CoA destination (NAS or Proxy)
Definition: realms.h:41
Configuration AVP similar to a VALUE_PAIR.
Definition: conffile.c:82
Definition: token.h:45
32 Bit unsigned integer.
Definition: radius.h:34
time_t time_all_dead
Definition: realms.h:171
char const * fr_strerror(void)
Get the last library error.
Definition: log.c:212
int strcasecmp(char *s1, char *s2)
Definition: missing.c:73
int num_home_servers
Definition: realms.h:173
static int realm_add(realm_config_t *rc, CONF_SECTION *cs)
Definition: realms.c:1761
CONF_SECTION * cf_section_sub_find(CONF_SECTION const *, char const *name)
Find a sub-section in a section.
Definition: conffile.c:3708
#define RETRY_DELAY
Definition: radiusd.h:326
int realm_realm_add(REALM *r, UNUSED CONF_SECTION *cs)
Definition: realms.c:1959
char const * cf_section_name1(CONF_SECTION const *cs)
Definition: conffile.c:3592
bool dual
One of a pair of homeservers on consecutive ports.
Definition: realms.h:74
uint32_t idle_timeout
Definition: realms.h:65
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type)
Allocate a CONF_PAIR.
Definition: conffile.c:546
#define PW_TYPE_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition: conffile.h:211
char const * log_name
The name used for log messages.
Definition: realms.h:69
bool home_servers_udp
Whether there are any UDP home servers.
Definition: realms.c:38
home_pool_type_t type
Definition: realms.h:162
#define RDEBUG2(fmt,...)
Definition: log.h:244
static int realm_name_cmp(void const *one, void const *two)
Definition: realms.c:111
static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r)
Definition: realms.c:1581
void realm_pool_free(home_pool_t *pool)
Definition: realms.c:1011
home_server_t * home_server_byname(char const *name, int type)
Definition: realms.c:2679
home_server_t * home_server_find(fr_ipaddr_t *ipaddr, uint16_t port, int proto)
Definition: realms.c:2660
uint32_t max_outstanding
Maximum outstanding requests.
Definition: realms.h:103
uint8_t data[]
Definition: eap_pwd.h:625
home_server_t * fallback
Definition: realms.h:169
uint32_t coa_mrc
Definition: realms.h:132
void realms_free(void)
Definition: realms.c:256
static realm_config_t * realm_config
Definition: realms.c:80
bool event_loop_started
Whether the main event loop has been started yet.
Definition: mainconfig.c:50
#define TAG_ANY
Definition: pair.h:191
home_ping_check_t ping_check
What method we use to perform the 'ping' none, status-server or fake request.
Definition: realms.h:116
struct timeval timestamp
When we started processing the request.
Definition: radiusd.h:214
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
log_lvl_t rad_debug_lvl
Global debugging level.
Definition: log.c:49
home_ping_check_t
Definition: realms.h:45
char const * name
Definition: realms.h:179
int state
Definition: realms.h:113
bool rbtree_insert(rbtree_t *tree, void *data)
Definition: rbtree.c:329
void void void fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t slen, char const *msg)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
Definition: log.c:359
char const * src_ipaddr_str
Need to parse the string specially as it may require a DNS lookup and the address family for that is ...
Definition: realms.h:84
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
home_pool_t * home_pool_byname(char const *name, int type)
Definition: realms.c:2704
char const * virtual_server
Definition: realms.h:167
static ssize_t xlat_home_server(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt) CC_HINT(nonnull)
xlat for %{home_server:foo}
Definition: realms.c:224
CONF_SECTION * cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2)
Allocate a CONF_SECTION.
Definition: conffile.c:626
#define WARN(fmt,...)
Definition: log.h:144
static char const * secret
Definition: radclient.c:44
static ssize_t xlat_server_pool(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt) CC_HINT(nonnull)
xlat for %{home_server_pool:foo}
Definition: realms.c:243
#define PW_AUTH_UDP_PORT
Definition: radius.h:114
static const FR_NAME_NUMBER home_ping_check[]
Definition: realms.c:73
struct timeval init_delay
Initial request processing delay.
Definition: radiusd.h:153
#define RBTREE_FLAG_LOCK
Definition: libradius.h:527
uint32_t currently_outstanding
Definition: realms.h:104
uint32_t max_response_timeouts
Definition: realms.h:102
static rbtree_t * home_servers_bynumber
Definition: realms.c:87
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
Definition: pair.c:639
home_server_t * home_server
Definition: radiusd.h:240
CONF_SECTION * home_server_cs_afrom_client(CONF_SECTION *client)
Fixup a client configuration section to specify a home server.
Definition: realms.c:889
static rbtree_t * home_pools_byname
Definition: realms.c:90
static int home_server_max_number
Definition: realms.c:86
#define pthread_mutex_lock(_x)
Definition: rlm_eap.h:77
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
IPv4/6 prefix.
Definition: inet.h:41
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
Definition: token.c:506
int number
Definition: realms.h:141
char const * parent_server
Definition: realms.h:76
void * cf_data_find(CONF_SECTION const *, char const *)
Definition: conffile.c:3981
uint32_t retry_count
Definition: realms.c:58
CONF_PAIR * cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp)
Duplicate a CONF_PAIR.
Definition: conffile.c:589
String of printable characters.
Definition: radius.h:33
uint32_t coa_mrt
Definition: realms.h:133
#define FR_CONF_POINTER(_n, _t, _p)
Definition: conffile.h:172
home_pool_t * acct_pool
Definition: realms.h:184
#define RWDEBUG(fmt,...)
Definition: log.h:251
#define PW_ACCT_UDP_PORT
Definition: radius.h:116
static bool home_server_insert(home_server_t *home, CONF_SECTION *cs)
Insert a new home server into the various internal lookup trees.
Definition: realms.c:450
CONF_SECTION * cf_section_sub_find_name2(CONF_SECTION const *, char const *name1, char const *name2)
Find a CONF_SECTION with both names.
Definition: conffile.c:3728
static const CONF_PARSER proxy_config[]
Definition: realms.c:95
#define RCSID(id)
Definition: build.h:135
static CONF_PARSER home_server_config[]
Definition: realms.c:303
Accounting server.
Definition: realms.h:37
static int r
Definition: rbmonkey.c:66
uint32_t revive_interval
How often we revive it (if it doesn't support pings).
Definition: realms.h:128
char * talloc_typed_strdup(void const *t, char const *p)
Call talloc strdup, setting the type on the new chunk correctly.
Definition: missing.c:588
32 Bit IPv4 Address.
Definition: radius.h:35
home_type_t type
Auth, Acct, CoA etc.
Definition: realms.h:82
char const * secret
Definition: realms.h:95
bool realm_home_server_add(home_server_t *home)
Add an already allocate home_server_t to the various trees.
Definition: realms.c:485
uint16_t port
Definition: realms.h:79
static const FR_NAME_NUMBER home_server_types[]
Definition: realms.c:65
VALUE_PAIR * fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps, char const *attribute, char const *value, FR_TOKEN op)
Create a VALUE_PAIR from ASCII strings.
Definition: pair.c:338
char const * name
Definition: realms.h:161
int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition: inet.c:1026
uint32_t lifetime
Definition: realms.h:64
#define FR_IPADDR_PREFIX_STRLEN
Like FR_IPADDR_STRLEN but with space for a prefix.
Definition: inet.h:71
bool dynamic
Definition: realms.c:60
#define fr_exit(_x)
Definition: libradius.h:508
uint32_t zombie_period
Unresponsive for T, mark it dead.
Definition: realms.h:111
int proto
TCP or UDP.
Definition: realms.h:91
#define ERROR(fmt,...)
Definition: log.h:145
Authentication server.
Definition: realms.h:36
16 Bit unsigned integer.
Definition: radius.h:43
fr_ipaddr_t ipaddr
IP address of home server.
Definition: realms.h:78
static int server_pool_add(realm_config_t *rc, CONF_SECTION *cs, home_type_t server_type, bool do_print)
Definition: realms.c:1130
char const * server
Definition: radiusd.h:289
char const * cf_section_name2(CONF_SECTION const *cs)
Definition: conffile.c:3601
bool fallback
Definition: realms.c:61
struct timeval response_window
Definition: realms.h:100
static int add_pool_to_realm(realm_config_t *rc, CONF_SECTION *cs, char const *name, home_pool_t **dest, home_type_t server_type, bool do_print)
Definition: realms.c:1712
#define RDEBUG3(fmt,...)
Definition: log.h:245