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