@@ -103,7 +103,18 @@ TMPL_REQUEST_REF_DEF(tmpl_request_def_parent, REQUEST_PARENT);
103103 *
104104 * Defaults are used if a NULL rules pointer is passed to the parsing function.
105105 */
106- #define DEFAULT_RULES tmpl_rules_t const default_rules = { .attr = { .list_def = request_attr_request }}
106+ #define DEFAULT_RULES tmpl_rules_t default_rules = { .attr = { .list_def = request_attr_request }}
107+
108+ #define CHECK_T_RULES do { \
109+ if (!t_rules) { \
110+ t_rules = &default_rules; \
111+ if (tmpl_require_enum_prefix) default_rules.attr.prefix = TMPL_ATTR_REF_PREFIX_AUTO; \
112+ } else if (tmpl_require_enum_prefix && (t_rules->attr.prefix == TMPL_ATTR_REF_PREFIX_YES)) { \
113+ default_rules = *t_rules; \
114+ default_rules.attr.prefix = TMPL_ATTR_REF_PREFIX_AUTO; \
115+ t_rules = &default_rules; \
116+ } \
117+ } while (0)
107118
108119
109120/* clang-format off */
@@ -541,11 +552,8 @@ static fr_slen_t tmpl_request_ref_list_from_substr(TALLOC_CTX *ctx, tmpl_attr_er
541552 tmpl_attr_rules_t const * at_rules ;
542553 DEFAULT_RULES ;
543554
544- if (!t_rules ) {
545- at_rules = & default_rules .attr ;
546- } else {
547- at_rules = & t_rules -> attr ;
548- }
555+ CHECK_T_RULES ;
556+ at_rules = & t_rules -> attr ;
549557
550558 /*
551559 * The caller wants to know the default namespace for
@@ -1076,6 +1084,11 @@ int tmpl_attr_copy(tmpl_t *dst, tmpl_t const *src)
10761084 tmpl_request_list_talloc_reverse_free (& dst -> data .attribute .rr );
10771085 tmpl_request_ref_list_copy (dst , & dst -> data .attribute .rr , & src -> data .attribute .rr );
10781086
1087+ /*
1088+ * Ensure that we copy over any parsing rules, defaults, etc.
1089+ */
1090+ dst -> rules = src -> rules ;
1091+
10791092 TMPL_ATTR_VERIFY (dst );
10801093
10811094 return 0 ;
@@ -1773,6 +1786,8 @@ static inline int tmpl_attr_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t
17731786 fr_dict_attr_err_t dict_err ;
17741787 fr_dict_attr_t const * our_parent = parent ;
17751788
1789+ fr_assert (!tmpl_require_enum_prefix || (vpt -> rules .attr .prefix != TMPL_ATTR_REF_PREFIX_YES ));
1790+
17761791 fr_sbuff_marker (& m_s , name );
17771792
17781793 if (depth > FR_DICT_MAX_TLV_STACK ) {
@@ -2163,6 +2178,8 @@ static inline int tmpl_attr_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t
21632178 if (tmpl_is_attr (vpt ) && tmpl_attr_tail_is_normal (vpt ) &&
21642179 (tmpl_rules_cast (vpt ) == tmpl_attr_tail_da (vpt )-> type )) vpt -> rules .cast = FR_TYPE_NULL ;
21652180
2181+ TMPL_VERIFY (vpt );
2182+
21662183 fr_sbuff_marker_release (& m_s );
21672184 return 0 ;
21682185}
@@ -2218,13 +2235,17 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
22182235 fr_sbuff_t our_name = FR_SBUFF (name ); /* Take a local copy in case we need to back track */
22192236 bool is_raw = false;
22202237 tmpl_attr_rules_t const * at_rules ;
2238+ tmpl_attr_rules_t our_at_rules ;
22212239 fr_sbuff_marker_t m_l ;
22222240 fr_dict_attr_t const * namespace ;
22232241 DEFAULT_RULES ;
22242242
2225- if (!t_rules ) t_rules = & default_rules ;
2243+ CHECK_T_RULES ;
2244+
22262245 at_rules = & t_rules -> attr ;
22272246
2247+ fr_assert (!tmpl_require_enum_prefix || (at_rules -> prefix != TMPL_ATTR_REF_PREFIX_YES ));
2248+
22282249 if (err ) * err = TMPL_ATTR_ERROR_NONE ;
22292250
22302251 if (!fr_sbuff_extend (& our_name )) {
@@ -2246,6 +2267,14 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
22462267 }
22472268 break ;
22482269 }
2270+
2271+ /*
2272+ * Rewrite the prefix parsing to "auto", which affects the printing.
2273+ */
2274+ our_at_rules = * at_rules ;
2275+ our_at_rules .prefix = TMPL_ATTR_REF_PREFIX_AUTO ;
2276+ at_rules = & our_at_rules ;
2277+
22492278 FALL_THROUGH ; /* if we do require enum prefixes, then the '&' is optional */
22502279
22512280 case TMPL_ATTR_REF_PREFIX_AUTO :
@@ -2270,6 +2299,7 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
22702299 */
22712300 MEM (vpt = tmpl_alloc (ctx , TMPL_TYPE_ATTR , T_BARE_WORD , NULL , 0 ));
22722301 vpt -> data .attribute .ref_prefix = TMPL_ATTR_REF_PREFIX_YES ;
2302+ vpt -> rules .attr .prefix = at_rules -> prefix ;
22732303
22742304 /*
22752305 * The "raw." prefix marks up the leaf attribute
@@ -2433,6 +2463,9 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
24332463 fr_assert (ar != NULL );
24342464
24352465 if (tmpl_attr_is_list_attr (ar )) vpt -> rules .attr .list_def = ar -> ar_da ;
2466+
2467+ fr_assert (!tmpl_require_enum_prefix || (vpt -> rules .attr .prefix != TMPL_ATTR_REF_PREFIX_YES ));
2468+
24362469 }
24372470
24382471 if (!tmpl_substr_terminal_check (& our_name , p_rules )) {
@@ -2478,7 +2511,7 @@ ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
24782511 ssize_t slen , name_len ;
24792512 DEFAULT_RULES ;
24802513
2481- if (! t_rules ) t_rules = & default_rules ; /* Use the defaults */
2514+ CHECK_T_RULES ;
24822515
24832516 name_len = strlen (name );
24842517 slen = tmpl_afrom_attr_substr (ctx , err , out , & FR_SBUFF_IN (name , name_len ), NULL , t_rules );
@@ -3188,7 +3221,7 @@ fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
31883221 tmpl_t * vpt = NULL ;
31893222 DEFAULT_RULES ;
31903223
3191- if (! t_rules ) t_rules = & default_rules ; /* Use the defaults */
3224+ CHECK_T_RULES ;
31923225
31933226 * out = NULL ;
31943227
@@ -3318,6 +3351,8 @@ fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
33183351 if (slen > 0 ) goto done_bareword ;
33193352 fr_assert (!* out );
33203353
3354+ fr_assert (!tmpl_require_enum_prefix || (t_rules -> attr .prefix != TMPL_ATTR_REF_PREFIX_YES ));
3355+
33213356 /*
33223357 * See if it's an attribute reference
33233358 * without the prefix.
@@ -3596,6 +3631,8 @@ tmpl_t *tmpl_copy(TALLOC_CTX *ctx, tmpl_t const *in)
35963631 if (unlikely (xlat_copy (vpt , vpt -> data .xlat .ex , in -> data .xlat .ex ) < 0 )) goto error ;
35973632 }
35983633
3634+ TMPL_ATTR_VERIFY (vpt );
3635+
35993636 return vpt ;
36003637}
36013638
@@ -4265,6 +4302,8 @@ int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules)
42654302 fr_assert (0 );
42664303 }
42674304
4305+ TMPL_VERIFY (vpt );
4306+
42684307 return ret ;
42694308}
42704309
@@ -4644,6 +4683,13 @@ fr_slen_t tmpl_attr_print(fr_sbuff_t *out, tmpl_t const *vpt, tmpl_attr_prefix_t
46444683 return 0 ;
46454684 }
46464685
4686+ /*
4687+ * Suppress the prefix on new syntax.
4688+ */
4689+ if (tmpl_require_enum_prefix && (ar_prefix == TMPL_ATTR_REF_PREFIX_YES )) {
4690+ ar_prefix = TMPL_ATTR_REF_PREFIX_AUTO ;
4691+ }
4692+
46474693 /*
46484694 * Handle printing the request reference
46494695 * prefix.
@@ -4837,6 +4883,13 @@ fr_slen_t tmpl_print(fr_sbuff_t *out, tmpl_t const *vpt,
48374883
48384884 TMPL_VERIFY (vpt );
48394885
4886+ /*
4887+ * Suppress the prefix on new syntax.
4888+ */
4889+ if (tmpl_require_enum_prefix && (ar_prefix == TMPL_ATTR_REF_PREFIX_YES )) {
4890+ ar_prefix = TMPL_ATTR_REF_PREFIX_AUTO ;
4891+ }
4892+
48404893 switch (vpt -> type ) {
48414894 case TMPL_TYPE_ATTR_UNRESOLVED :
48424895 case TMPL_TYPE_ATTR :
@@ -4993,6 +5046,8 @@ void tmpl_attr_verify(char const *file, int line, tmpl_t const *vpt)
49935046
49945047 fr_assert (tmpl_is_attr_unresolved (vpt ) || tmpl_is_attr (vpt ));
49955048
5049+ fr_assert (!tmpl_require_enum_prefix || (vpt -> rules .attr .prefix != TMPL_ATTR_REF_PREFIX_YES ));
5050+
49965051 /*
49975052 * Loop detection
49985053 */
@@ -5781,6 +5836,8 @@ void tmpl_rules_child_init(TALLOC_CTX *ctx, tmpl_rules_t *out, tmpl_rules_t cons
57815836
57825837 if (!tmpl_is_attr (vpt )) return ;
57835838
5839+ fr_assert (!tmpl_require_enum_prefix || (vpt -> rules .attr .prefix != TMPL_ATTR_REF_PREFIX_YES ));
5840+
57845841 da = tmpl_attr_tail_da (vpt );
57855842
57865843 /*
0 commit comments