@@ -532,6 +532,8 @@ static CONF_PARSER home_server_config[] = {
532532 { "username" , FR_CONF_OFFSET (PW_TYPE_STRING | PW_TYPE_NOT_EMPTY , home_server_t , ping_user_name ), NULL },
533533 { "password" , FR_CONF_OFFSET (PW_TYPE_STRING | PW_TYPE_NOT_EMPTY , home_server_t , ping_user_password ), NULL },
534534
535+ { "affinity" , FR_CONF_OFFSET (PW_TYPE_INTEGER , home_server_t , affinity ), NULL },
536+
535537#ifdef WITH_STATS
536538 { "historic_average_window" , FR_CONF_OFFSET (PW_TYPE_INTEGER , home_server_t , ema .window ), NULL },
537539#endif
@@ -634,6 +636,8 @@ void realm_home_server_sanitize(home_server_t *home, CONF_SECTION *cs)
634636 if (parent && strcmp (cf_section_name1 (parent ), "server" ) == 0 ) {
635637 home -> parent_server = cf_section_name2 (parent );
636638 }
639+
640+ FR_INTEGER_BOUND_CHECK ("coa_mrt" , home -> affinity , <=, 255 );
637641}
638642
639643/** Insert a new home server into the various internal lookup trees
@@ -1636,6 +1640,35 @@ static int server_pool_add(realm_config_t *rc,
16361640 }
16371641 }
16381642
1643+ if (home -> affinity ) {
1644+ if (home -> virtual_server ) {
1645+ ERROR ("Home server %s is a virtual server, and cannot be used with 'affinity'" , home -> name );
1646+ goto error ;
1647+ }
1648+
1649+ if (!pool -> affinity_group ) {
1650+ pool -> affinity_group = talloc_zero_array (pool , home_server_t * , pool -> num_home_servers );
1651+ if (!pool -> affinity_group ) {
1652+ ERROR ("Out of memory" );
1653+ goto error ;
1654+ }
1655+ }
1656+
1657+ if (home -> affinity >= (uint32_t ) pool -> num_home_servers ) {
1658+ ERROR ("Home server %s has invalid 'affinity' value %u. It must be less than %u" ,
1659+ home -> name , home -> affinity , home -> affinity , pool -> num_home_servers );
1660+ goto error ;
1661+ }
1662+
1663+ if (pool -> affinity_group [home -> affinity ]) {
1664+ ERROR ("Home server %s has invalid 'affinity' value %u. That value is already used by home server %s" ,
1665+ home -> name , home -> affinity , pool -> affinity_group [home -> affinity ]-> name );
1666+ goto error ;
1667+ }
1668+
1669+ pool -> affinity_group [home -> affinity ] = home ;
1670+ }
1671+
16391672 if (!home ) {
16401673 ERROR ("Failed to find home server %s" , value );
16411674 goto error ;
@@ -1645,8 +1678,13 @@ static int server_pool_add(realm_config_t *rc,
16451678 pool -> servers [num_home_servers ++ ] = home ;
16461679 } /* loop over home_server's */
16471680
1648- if (pool -> fallback && do_print ) {
1649- cf_log_info (cs , "\tfallback = %s" , pool -> fallback -> name );
1681+ if (pool -> fallback ) {
1682+ if (do_print ) cf_log_info (cs , "\tfallback = %s" , pool -> fallback -> name );
1683+
1684+ if (pool -> affinity_group ) {
1685+ ERROR ("Cannot use home server pool 'fallback' when home server 'affinity' is set" );
1686+ goto error ;
1687+ }
16501688 }
16511689
16521690 if (!realm_pool_add (pool , cs )) goto error ;
@@ -2770,7 +2808,7 @@ void home_server_update_request(home_server_t *home, REQUEST *request)
27702808}
27712809
27722810home_server_t * home_server_ldb (char const * realmname ,
2773- home_pool_t * pool , REQUEST * request )
2811+ home_pool_t * pool , REQUEST * request )
27742812{
27752813 int start ;
27762814 int count ;
@@ -2779,6 +2817,26 @@ home_server_t *home_server_ldb(char const *realmname,
27792817 VALUE_PAIR * vp ;
27802818 uint32_t hash ;
27812819
2820+ /*
2821+ * Over-ride the pool configuration if the pool is marked up as having affinity, AND the packet has a State attribute.
2822+ */
2823+ if (pool -> affinity_group &&
2824+ (request -> packet -> code == PW_CODE_ACCESS_REQUEST ) &&
2825+ ((vp = fr_pair_find_by_num (request -> packet -> vps , PW_STATE , 0 , TAG_ANY )) != NULL ) &&
2826+ (vp -> vp_length > 1 ) &&
2827+ (vp -> vp_octets [0 ] < (uint32_t ) pool -> num_home_servers ) &&
2828+ (pool -> affinity_group [vp -> vp_octets [0 ]] != NULL )) {
2829+ found = pool -> affinity_group [vp -> vp_octets [0 ]];
2830+
2831+ if (HOME_SERVER_IS_DEAD (found )) return NULL ;
2832+
2833+ /*
2834+ * Get rid of the extra octet that we added on the outbound proxying.
2835+ */
2836+ fr_pair_value_memcpy (vp , vp -> vp_octets + 1 , vp -> vp_length - 1 );
2837+ return found ;
2838+ }
2839+
27822840 /*
27832841 * Determine how to pick choose the home server.
27842842 */
0 commit comments