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