@@ -57,6 +57,29 @@ int unlang_load_balance_persist(request_t *request)
5757 return request_data_add_const (request , frame -> instruction , 0 , child , true);
5858}
5959
60+ /** Returns the current child of the load balance section
61+ *
62+ * If the frame is UNLANG_TYPE_LOAD_BALANCE or
63+ * UNLANG_TYPE_REDUNDANT_LOAD_BALANCE, then return the child number.
64+ */
65+ uint8_t unlang_load_balance_child (request_t * request )
66+ {
67+ unlang_stack_t * stack = request -> stack ;
68+ unlang_stack_frame_t * frame = & stack -> frame [stack -> depth ];
69+ unlang_frame_state_redundant_t * redundant ;
70+
71+ if (!frame -> prev .frame_load_balance ) return 0 ;
72+
73+ fr_assert (frame -> prev .frame_load_balance < stack -> depth );
74+
75+ frame = & stack -> frame [frame -> prev .frame_load_balance ];
76+ redundant = talloc_get_type_abort (frame -> state , unlang_frame_state_redundant_t );
77+
78+ fr_assert (redundant -> num <= UINT8_MAX );
79+
80+ return redundant -> num ;
81+ }
82+
6083#define unlang_redundant_load_balance unlang_load_balance
6184
6285static unlang_action_t unlang_load_balance_next (unlang_result_t * p_result , request_t * request ,
@@ -98,7 +121,12 @@ static unlang_action_t unlang_load_balance_next(unlang_result_t *p_result, reque
98121 * end, loop around to the next one.
99122 */
100123 redundant -> child = unlang_list_next (& g -> children , redundant -> child );
101- if (!redundant -> child ) redundant -> child = unlang_list_head (& g -> children );
124+ if (!redundant -> child ) {
125+ redundant -> child = unlang_list_head (& g -> children );
126+ redundant -> num = 0 ;
127+ } else {
128+ redundant -> num ++ ;
129+ }
102130
103131 /*
104132 * We looped back to the start. Return whatever results we had from the last child.
@@ -161,7 +189,24 @@ static unlang_action_t unlang_load_balance(unlang_result_t *p_result, request_t
161189 redundant = talloc_get_type_abort (frame -> state , unlang_frame_state_redundant_t );
162190
163191 redundant -> start = request_data_get (request , frame -> instruction , 0 );
164- if (redundant -> start ) goto selected_child ;
192+ if (redundant -> start ) {
193+ uint32_t i ;
194+
195+ /*
196+ * This loop should be small, typically less than 16 items.
197+ */
198+ for (i = 0 ; i < unlang_list_num_elements (& g -> children ); i ++ ) {
199+ if (gext -> children [i ] != redundant -> start ) continue ;
200+
201+ redundant -> num = i ;
202+ RDEBUG3 ("load-balance starting at child %u" , redundant -> num );
203+ goto selected_child ;
204+ }
205+
206+ fr_assert (0 );
207+
208+ goto selected_child ;
209+ }
165210
166211 if (gext -> vpt ) {
167212 uint32_t start ;
@@ -205,9 +250,10 @@ static unlang_action_t unlang_load_balance(unlang_result_t *p_result, request_t
205250 }
206251 talloc_free (to_free );
207252
208- RDEBUG3 ("load-balance starting at child %d" , ( int ) start );
253+ RDEBUG3 ("load-balance starting at child %u" , start );
209254
210255 redundant -> start = gext -> children [start ];
256+ redundant -> num = start ;
211257
212258 } else {
213259 uint32_t start , one , two ;
@@ -231,8 +277,9 @@ static unlang_action_t unlang_load_balance(unlang_result_t *p_result, request_t
231277 start = two ;
232278 }
233279
234- RDEBUG3 ("load-balance starting at child %d" , ( int ) start );
280+ RDEBUG3 ("load-balance starting at child %u" , start );
235281 redundant -> start = gext -> children [start ];
282+ redundant -> num = start ;
236283 }
237284
238285selected_child :
@@ -282,6 +329,17 @@ static unlang_t *compile_load_balance_subsection(unlang_t *parent, unlang_compil
282329
283330 g = unlang_generic_to_group (c );
284331
332+ /*
333+ * The various State mangling functions need to limit the number of load-balance sections.
334+ *
335+ * Plus, it doesn't make a lot of sense to have 256 children of a load-balance section. Just
336+ * what the heck are they doing?
337+ */
338+ if (unlang_list_num_elements (& g -> children ) > UINT8_MAX ) {
339+ cf_log_err (cs , "Too many children for %s section" , c -> name );
340+ return NULL ;
341+ }
342+
285343 /*
286344 * Inside of the "modules" section, it's a virtual module. The key is the third argument, and
287345 * the "name2" is the module name, which we ignore here.
0 commit comments