*** raddb/proxy.conf.orig	Wed Jan 11 22:09:02 2006
--- raddb/proxy.conf	Fri Sep 15 19:31:02 2006
***************
*** 158,164 ****
--- 158,191 ----
  #	nostrip
  #}
  
+ #  A realm containing a regular expression, matching anything like
+ #  "user@company2.com" as well as "user@host.company2.com". All 
+ #  requests with the matching realms will be sent to radius.company2.com.
  #
+ #  Please note that the regular expressions must be POSIX compatible
+ #  and will be matched case insensitive.
+ #  Additionally, the regex should be the same on all servers of
+ #  a fail-over and round-robin realm.
+ #
+ #  If there are more than one realms matching the regex, the first
+ #  matching entry in this file (proxy.conf) will be used.
+ #
+ #  Attention!
+ #  Be careful not to make any loop among radius servers. The server
+ #  radius.company2.com must catch all the non-existing realms such
+ #  as @[no_domain].company2.com so that the requests won't propagate
+ #  further or backward.
+ #
+ #realm company2.com {
+ #	regex		= "^.*company2\.com$"
+ #	type		= radius
+ #	authhost	= radius.company2.com
+ #	accthost	= radius.company2.com
+ #	secret		= TheirKey
+ #	nostrip
+ #}
+ 
+ #
  #  1st node serv.com...set up for round-robin.
  #
  #  The load balancing 'ldflag' attribute can be used to perform
*** src/include/radiusd.h.orig	Tue Apr 12 08:45:21 2005
--- src/include/radiusd.h	Thu Sep 14 20:00:32 2006
***************
*** 35,40 ****
--- 35,44 ----
  #include <arpa/inet.h>
  #endif
  
+ #ifdef HAVE_REGEX_H
+ #include <regex.h>
+ #endif
+ 
  #include "missing.h"
  
  #define NO_SUCH_CHILD_PID (child_pid_t) (0)
***************
*** 139,144 ****
--- 143,152 ----
  	int			acct_active;
  	time_t			acct_wakeup;
  	int			ldflag;
+ #ifdef HAVE_REGEX_H
+ 	regex_t			*regex;
+ #endif
+ 
  	struct _realm		*next;
  } REALM;
  
***************
*** 327,332 ****
--- 335,341 ----
  void		clients_free(RADCLIENT *cl);
  
  /* files.c */
+ int		realm_find_cmp(const REALM *rlm, const char *realm);
  REALM		*realm_find(const char *, int);
  REALM		*realm_findbyaddr(uint32_t ipno, int port);
  void		realm_free(REALM *cl);
*** src/main/files.c.orig	Wed Apr  7 05:43:49 2004
--- src/main/files.c	Thu Sep 14 20:00:32 2006
***************
*** 33,38 ****
--- 33,42 ----
  #	include <netinet/in.h>
  #endif
  
+ #ifdef HAVE_REGEX_H
+ #	include <regex.h>
+ #endif
+ 
  #include <stdlib.h>
  #include <string.h>
  #include <netdb.h>
***************
*** 314,319 ****
--- 318,329 ----
  
  	while(cl) {
  		next = cl->next;
+ #ifdef HAVE_REGEX_H
+ 		if (cl->regex != NULL) {
+ 			regfree(cl->regex);
+ 			free(cl->regex);
+ 		}
+ #endif
  		free(cl);
  		cl = next;
  	}
***************
*** 435,440 ****
--- 445,458 ----
  		c->active = TRUE;
  		c->acct_active = TRUE;
  
+ 		/*
+ 		 * Regular expressions for realms are not supported 
+ 		 * with the old-style realm file
+ 		 */
+ #ifdef HAVE_REGEX_H
+ 		c->regex = NULL;
+ #endif
+ 
  		while (getword(&p, opts, sizeof(opts))) {
  			if (strcmp(opts, "nostrip") == 0)
  				c->striprealm = FALSE;
***************
*** 504,509 ****
--- 522,542 ----
  }
  
  /*
+  *      Compare a realm name with entry
+  *      If enabled also compare with regex
+  */
+ int realm_find_cmp(const REALM *rlm, const char *realm) {
+ #ifdef HAVE_REGEX_H
+        	if ((rlm->regex != NULL) &&
+        	       	(regexec(rlm->regex, realm, 0, NULL, 0) == 0)) {
+        	       	return 0;
+        	}
+ #endif /* HAVE_REGEX_H */
+ 
+         return(strcasecmp(rlm->realm, realm));
+ }
+ 
+ /*
   *	Find a realm in the REALM list.
   */
  REALM *realm_find(const char *realm, int accounting)
***************
*** 548,554 ****
  			 *	dead.
  			 */
  			if ((!mainconfig.proxy_fallback) &&
! 			    (strcasecmp(cl->realm, realm) == 0)) {
  				dead_match = 1;
  			}
  			continue;
--- 581,587 ----
  			 *	dead.
  			 */
  			if ((!mainconfig.proxy_fallback) &&
! 			    (realm_find_cmp(cl, realm) == 0)) {
  				dead_match = 1;
  			}
  			continue;
***************
*** 562,568 ****
  		 *	scatter techniques, as that's more properly
  		 *	the responsibility of the proxying code.
  		 */
! 		if (strcasecmp(cl->realm, realm) == 0) {
  			return cl;
  		}
  
--- 595,601 ----
  		 *	scatter techniques, as that's more properly
  		 *	the responsibility of the proxying code.
  		 */
! 		if (realm_find_cmp(cl, realm) == 0) {
  			return cl;
  		}
  
***************
*** 585,591 ****
  		if (mainconfig.wake_all_if_all_dead) {
  			REALM *rcl = NULL;
  			for (cl = mainconfig.realms; cl; cl = cl->next) {
! 				if(strcasecmp(cl->realm,realm) == 0) {
  					if (!accounting && !cl->active) {
  						cl->active = TRUE;
  						rcl = cl;
--- 618,624 ----
  		if (mainconfig.wake_all_if_all_dead) {
  			REALM *rcl = NULL;
  			for (cl = mainconfig.realms; cl; cl = cl->next) {
! 				if(realm_find_cmp(cl,realm) == 0) {
  					if (!accounting && !cl->active) {
  						cl->active = TRUE;
  						rcl = cl;
*** src/main/mainconfig.c.orig	Wed Apr 19 02:26:26 2006
--- src/main/mainconfig.c	Thu Sep 14 20:00:32 2006
***************
*** 35,40 ****
--- 35,44 ----
  #include <arpa/inet.h>
  #endif
  
+ #ifdef HAVE_REGEX_H
+ #include <regex.h>
+ #endif
+ 
  #include "radiusd.h"
  #include "rad_assert.h"
  #include "conffile.h"
***************
*** 493,498 ****
--- 497,526 ----
  
  		c->striprealm = 1;
  
+ #ifdef HAVE_REGEX_H
+ 		/*
+ 		 *	If the realm has a regex configured, try to
+ 		 *	precompile it and store it in the realm struct.
+ 		 */
+ 		char *regex = cf_section_value_find(cs, "regex");
+ 		if (regex != NULL && strcmp(c->realm, "NULL") && strcmp(c->realm, "DEFAULT")) {
+ 			DEBUG2("read_config_files:  found a regular expression for realm %s, trying to compile it",
+ 			       c->realm);
+ 			c->regex = rad_malloc(sizeof(regex_t));
+ 
+ 			int res = regcomp(c->regex, regex, REG_NOSUB|REG_ICASE);
+ 			if (res != 0) {
+ 				char msg[128];
+ 
+ 				regerror(res, c->regex, msg, sizeof(msg));
+ 				radlog(L_ERR, "%s[%d]: Found illegal regular expression %s, disabling regex support for realm %s.",
+ 				       filename, cf_section_lineno(cs), msg, c->realm);
+ 
+ 				return -1;
+ 			}
+ 		}
+ #endif
+ 
  		if ((cf_section_value_find(cs, "nostrip")) != NULL)
  			c->striprealm = 0;
  		if ((cf_section_value_find(cs, "noacct")) != NULL)
*** src/main/proxy.c.orig	Thu Dec  8 22:24:32 2005
--- src/main/proxy.c	Thu Sep 14 20:00:32 2006
***************
*** 158,164 ****
  		/*
  		 *	The realm name doesn't match, skip it.
  		 */
! 		if (strcasecmp(cl->realm, realm_name) != 0) {
  			continue;
  		}
  
--- 158,164 ----
  		/*
  		 *	The realm name doesn't match, skip it.
  		 */
! 		if (realm_find_cmp(cl, realm_name) != 0) {
  			continue;
  		}
  
