From: Alan T. DeKok Date: Fri, 9 Oct 2020 18:48:54 +0000 (-0400) Subject: add ALIAS support X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=547b79fdb01a794f2da7fbbd16f8155bcb552ca1;p=thirdparty%2Ffreeradius-server.git add ALIAS support which is a simpler way of defining multiple names for one attribute. This keyword allows aliasing of the name, without the need to repeat number, data type, etc. At some point we will forbid duplicate ATTRIBUTE definitions, and instead require the use of ALIAS --- diff --git a/man/man5/dictionary.5 b/man/man5/dictionary.5 index 90ae5e2a0c1..7c129d9d0ff 100644 --- a/man/man5/dictionary.5 +++ b/man/man5/dictionary.5 @@ -10,7 +10,7 @@ .RE .sp .. -.TH dictionary 5 "14 May 2019" +.TH dictionary 5 "09 Oct 2020" .SH NAME dictionary \- RADIUS dictionary file .SH DESCRIPTION @@ -43,9 +43,24 @@ Every line starting with a hash sign is treated as comment and ignored. .PP Each line of the file can contain one of the following strings: +.TP 0.5i +.B ALIAS new-name old-name +Define an alias \fInew-name\fP which is equivalent to \fIold-name\fP. + +The ALIAS keyword is used to define additional names for compatibility +reasons. As there is no standard behind dictionary names, different +products may use different names for the same attribute. The ALIAS +keyword allows you to add "site local" aliases, so that FreeRADIUS can +read attributes from pre-existing configurations. + +These ALIASes are used when the server reads configuration files, or +attributes from a database. However, when the server prints attribute +names, it always uses the ATTRIBUTE definition from the FreeRADIUS +dictionary files/ + .TP 0.5i .B ATTRIBUTE name oid type [flags] -Define a RADIUS attribute name to number mapping. +Define an attribute name to number mapping. The \fIname\fP field is a printable field, taken from various specifications or vendor definitions. It is most commonly used as a diff --git a/scripts/dict/format.pl b/scripts/dict/format.pl index c9582106e4a..5d438df72bb 100755 --- a/scripts/dict/format.pl +++ b/scripts/dict/format.pl @@ -290,6 +290,20 @@ while (@ARGV) { next; } + # + # Get ALIAS + # + if (/^ALIAS\s+([-\w]+)\s+(\w+)(.*)/) { + $name=$1; + $tabs = tabs(40, $name); + + $ref = $2; + $stuff = $3; + + push @output, "ALIAS\t\t$name$tabs$ref$stuff\n"; + next; + } + # # VALUE attr name value # diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index c02d37017d2..cd9914f6b6b 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -518,6 +518,60 @@ static fr_dict_attr_t const *dict_gctx_unwind(dict_tokenize_ctx_t *ctx) return ctx->stack[ctx->stack_depth].da; } +/* + * Process the ALIAS command + */ +static int dict_read_process_alias(dict_tokenize_ctx_t *ctx, char **argv, int argc) +{ + fr_dict_attr_t const *da; + + if (argc != 2) { + fr_strerror_printf("Invalid ALIAS syntax"); + return -1; + } + + /* + * Dictionaries need to have real names, not shitty ones. + */ + if (strncmp(argv[0], "Attr-", 5) == 0) { + fr_strerror_printf("Invalid ALIAS name"); + return -1; + } + + da = dict_attr_by_name(ctx->dict, argv[0]); + if (da) { + fr_strerror_printf("Attribute %s already exists", argv[0]); + return -1; + } + + /* + * The can be a name. + */ + da = dict_attr_by_name(ctx->dict, argv[1]); + if (!da) { + fr_strerror_printf("Attribute %s does not exist", argv[1]); + return -1; + + } + + /* + * Note that we do NOT call fr_dict_attr_add() here. + * When that function adds two equivalent attributes the + * second one is prioritized for printing. For ALIASes, + * we want the first one to be prioritized. + */ + da = dict_attr_alloc(ctx->dict->pool, da->parent, argv[0], da->attr, da->type, &da->flags); + if (!da) return -1; + + if (!fr_hash_table_insert(ctx->dict->attributes_by_name, da)) { + fr_strerror_printf("Internal error storing attribute"); + talloc_const_free(da); + return -1; + } + + return 0; +} + /* * Process the ATTRIBUTE command */ @@ -1761,6 +1815,15 @@ static int _dict_from_file(dict_tokenize_ctx_t *ctx, return -1; } + /* + * Perhaps this is an attribute. + */ + if (strcasecmp(argv[0], "ALIAS") == 0) { + if (dict_read_process_alias(ctx, + argv + 1, argc - 1) == -1) goto error; + continue; + } + /* * Perhaps this is an attribute. */