#
dead_time = 120
+# If you choose to list a realm more then once for fall-through or
+# round-robin, then specify the total number of alternates here. Specify
+# a ldflag attribute for all realms to be included in a round-robin
+# setup. Currently (0 or fail_over) and (1 or round_robin) are the
+# supported values for ldflag. Fail-Over is the default setup.
+#
+ servers_per_realm = 5
+
#
# If all exact matching realms did not respond, we can try the
# DEFAULT realm, too. This is what the server normally does.
# nostrip
#}
+#
+# 1st node serv.com...set up for round-robin.
+# The ldflag attribute must be specified on all
+# realms included in a rr scheme. ldflag may also
+# be set as zero on realms using fail-over. Currently
+# (0 or fail_over) and (1 or round_robin) are the only
+# accepted values for ldflag. Fail-Over is the default setup.
+#
+#realm serv.com {
+# type = radius
+# authhost = radius.serv.com:1645
+# accthost = radius.serv.com:1646
+# secret = TheirKey
+# ldflag = round_robin
+# nostrip
+#}
+
+#
+# Another node for serv.com
+#
+#realm serv.com {
+# type = radius
+# authhost = radius2.serv.com:1645
+# accthost = radius2.serv.com:1646
+# secret = TheirKey2
+# ldflag = round_robin
+# nostrip
+#}
+
+#
+# A third round-robin node realm for serv.com
+#
+#realm serv.com {
+# type = radius
+# authhost = radius3.serv.com:1645
+# accthost = radius3.serv.com:1646
+# secret = TheirKey2
+# ldflag = round_robin
+# nostrip
+#}
+#
+#
+
#realm company.com {
# type = radius
# authhost = radius.company.com:1600
time_t wakeup;
int acct_active;
time_t acct_wakeup;
+ int ldflag;
+ int chose;
+ int node;
+ int total;
struct _realm *next;
} REALM;
#define RETRY_DELAY 5
#define RETRY_COUNT 3
#define DEAD_TIME 120
+#define MAX_PROXIES 15
#define L_DBG 1
#define L_AUTH 2
void pairlist_free(PAIR_LIST **);
int read_config_files(void);
int read_realms_file(const char *file);
+extern void check_proxies(int);
/* nas.c */
int read_naslist_file(char *);
*/
extern RADCLIENT *clients;
extern REALM *realms;
+extern int max_proxies;
static int generate_realms(const char *filename);
static int generate_clients(const char *filename);
CONF_SECTION *cs;
REALM *my_realms = NULL;
REALM *c, **tail;
- char *s, *authhost, *accthost;
+ char *s, *t, *authhost, *accthost;
tail = &my_realms;
for (cs = cf_subsection_find_next(config, NULL, "realm"); cs != NULL;
c->notrealm = 1;
if ((cf_section_value_find(cs, "notsuffix")) != NULL)
c->notrealm = 1;
+ if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
+ if ((strcmp(t,"1") == 0) ||
+ (strcasecmp(t,"round_robin") == 0)) {
+ c->ldflag = 1;
+ }
+ else if ((strcmp(t,"0") == 0) ||
+ (strcasecmp(t,"fail_over") == 0)) {
+ c->ldflag = 0;
+ }
+ else {
+ /* set to invalid value
+ * to be caught later
+ */
+ c->ldflag = -1;
+ }
+ }
+ else {
+ c->ldflag = 0;
+ }
c->active = TRUE;
c->acct_active = TRUE;
*/
*tail = realms;
realms = my_realms;
+
+ /*Setup node and total info for multi-listed realms*/
+ for (c = realms; c; c = c->next) {
+ if(c->chose == 1) {
+ continue;
+ }
+ else {
+ int i = 0, b = 0;
+ REALM *rptr, *r_array[max_proxies];
+ for(rptr = c; rptr; rptr = rptr->next) {
+ /*if realm matches*/
+ if(strcasecmp(rptr->realm, c->realm) == 0) {
+ i++;
+ r_array[i] = rptr;
+ rptr->chose = 1;
+ rptr->node = i;
+ }
+ }
+ if (i > 1) {
+ for(b = 1; b <= i; b++) {
+ rptr = r_array[b];
+ rptr->total = i;
+ }
+ }
+ else {
+ c->total = 0;
+ }
+ }
+ }
+
+ /*Set chose flag back to default (0) on all realms*/
+ for (c = realms; c; c = c->next) {
+ c->chose = 0;
+ }
return 0;
}
#include "radiusd.h"
extern int proxy_dead_time;
+int maximum_proxies;
REALM *realms = NULL;
*/
REALM *realm_find(const char *realm, int acct)
{
- REALM *cl;
+ REALM *cl, *realmptr;
REALM *default_realm = NULL;
+ REALM *rr_array[maximum_proxies];
time_t now;
- int dead_match = 0;
+ int dead_match = 0, efform = 0, p = 0, i = 0;
+ static int proxy_return;
now = time(NULL);
-
/*
* If we're passed a NULL realm pointer,
* then look for a "NULL" realm string.
if (realm == NULL) {
realm = "NULL";
}
-
+
for (cl = realms; cl; cl = cl->next) {
/*
* Wake up any sleeping realm.
* If it matches exactly, return it.
*/
if (strcasecmp(cl->realm, realm) == 0) {
- return cl;
+ /*
+ * Seperate parsing of list for round-robin
+ */
+ if(cl->total > 1 && cl->ldflag == 1) {
+ /*Get all of the realms from initial list*/
+ for(i = 1; i <= cl->total; i++) {
+ for(realmptr = realms; realmptr;
+ realmptr = realmptr->next) {
+ if((strcasecmp(realmptr->realm,
+ cl->realm)) == 0 &&
+ (realmptr->node == i)) {
+ rr_array[i] = realmptr;
+ if(realmptr->active == TRUE)
+ p++;
+ break;
+ }
+ else {
+ continue;
+ }
+ }
+ }
+ /*if only one realm active, return it*/
+ if(p == 1) {
+ for (p = 1; p < i; p++) {
+ realmptr = rr_array[p];
+ if(realmptr->active == TRUE) {
+ return realmptr;
+ }
+ }
+ }
+ for(p = 1; p < i; p++) {
+ realmptr = rr_array[p];
+ if(realmptr->chose == 1) {
+ efform++;
+ }
+ }
+
+ /*
+ * if none available,
+ * and last realm has
+ * been returned as access-reply
+ */
+
+ if(efform == cl->total && proxy_return == 0) {
+ for(p = 1; p < i; p++) {
+ realmptr = rr_array[p];
+ realmptr->chose = 0;
+ }
+ }
+
+ /*
+ * if this realm hasn't been chosen and
+ * this is not being returned for
+ * access reply
+ * else if the realm has been chosen
+ * and this is for access-reply
+ * else this realm is dead (reset if
+ * this is the last realm in the list)
+ */
+
+ for(p = 1; p < i; p++) {
+ realmptr = rr_array[p];
+ if((realmptr->chose == 0) &&
+ (proxy_return < realmptr->node) &&
+ (realmptr->active == TRUE && realmptr->acct_active == TRUE)
+ ) {
+ proxy_return = realmptr->node;
+ realmptr->chose = 1;
+ return realmptr;
+ }
+ else if ((realmptr->chose == 1) &&
+ (proxy_return == realmptr->node)
+ ) {
+ if(proxy_return + 1 > realmptr->total) {
+ proxy_return = 0;
+ }
+ realmptr->chose = 0;
+ return realmptr;
+ }
+ else
+ {
+ if((realmptr->active == FALSE ||
+ realmptr->acct_active == FALSE ) &&
+ (realmptr->node == realmptr->total)
+ ) {
+ proxy_return = 0;
+ }
+ continue;
+ }
+ }
+ }
+
+ /*
+ * else we have single
+ * realm or non-rr realm
+ */
+
+ else {
+ return cl;
+ }
}
/*
return NULL;
}
+
+/*
+ * Catch any errors in set-up of RR list or exceeding max_proxies
+ */
+void check_proxies(int max_config) {
+ REALM *next, *rptr;
+ if(max_config > 0) {
+ maximum_proxies = max_config;
+ for(rptr=realms; rptr; rptr = rptr->next) {
+ if(rptr->total > max_config || rptr->total >= 1) {
+ for(next = realms; next; next = next->next) {
+ if(next->ldflag != 0 &&
+ next->ldflag != 1) {
+ radlog(L_ERR,
+ "Invalid load balance flag on realm: %s entry %d\n",
+ next->realm, next->node);
+ exit(1);
+ }
+ else if((strcasecmp(rptr->realm, next->realm) == 0) &&
+ rptr->ldflag != next->ldflag){
+ radlog(L_ERR,
+ "Inconsistent ldflag for realm: %s entries %d and %d.\n",
+ rptr->realm, rptr->node, next->node);
+ exit(1);
+ }
+ else if (next->total > max_config) {
+ radlog(L_ERR,
+ "Too many entries (%d) for realm: %s. Max is %d.\n",
+ next->total, next->realm, max_config);
+ exit(1);
+ }
+ }
+ }
+ }
+ maximum_proxies++;
+ }
+}
int proxy_retry_delay = RETRY_DELAY;
int proxy_retry_count = RETRY_COUNT;
int proxy_dead_time = DEAD_TIME;
+int max_proxies = MAX_PROXIES;
int proxy_synchronous = FALSE;
int proxy_fallback = FALSE;
int need_reload = FALSE;
{ "synchronous", PW_TYPE_BOOLEAN, 0, &proxy_synchronous, "no" },
{ "default_fallback", PW_TYPE_BOOLEAN, 0, &proxy_fallback, "no" },
{ "dead_time", PW_TYPE_INTEGER, 0, &proxy_dead_time, Stringify(DEAD_TIME) },
+ { "servers_per_realm", PW_TYPE_INTEGER, 0, &max_proxies, Stringify(MAX_PROXIES) },
{ NULL, -1, 0, NULL, NULL }
};
/*
* Open Proxy Socket.
*/
+ check_proxies(max_proxies);
proxyfd = socket (AF_INET, SOCK_DGRAM, 0);
if (proxyfd < 0) {
perror ("proxy socket");
int proxy_retry_delay = RETRY_DELAY;
int proxy_retry_count = RETRY_COUNT;
int proxy_dead_time;
+int max_proxies = MAX_PROXIES;
int log_stripped_names;
struct main_config_t mainconfig;
int proxy_retry_delay = RETRY_DELAY;
int proxy_retry_count = RETRY_COUNT;
int proxy_dead_time;
+int max_proxies = MAX_PROXIES;
int log_stripped_names;
struct main_config_t mainconfig;
int proxy_retry_delay = RETRY_DELAY;
int proxy_retry_count = RETRY_COUNT;
int proxy_dead_time;
+int max_proxies = MAX_PROXIES;
int log_stripped_names;
radlog_dest_t radlog_dest = RADLOG_FILES;
const char *radutmp_file = NULL;