📄 dict.c
字号:
if (!fr_hash_table_insert(attributes_byname, attr)) { DICT_ATTR *a; /* * If the attribute has identical number, then * ignore the duplicate. */ a = fr_hash_table_finddata(attributes_byname, attr); if (a && (strcasecmp(a->name, attr->name) == 0)) { if (a->attr != attr->attr) { librad_log("dict_addattr: Duplicate attribute name %s", name); fr_pool_free(attr); return -1; } /* * Same name, same vendor, same attr, * maybe the flags and/or type is * different. Let the new value * over-ride the old one. */ } fr_hash_table_delete(attributes_byvalue, a); if (!fr_hash_table_replace(attributes_byname, attr)) { librad_log("dict_addattr: Internal error storing attribute %s", name); fr_pool_free(attr); return -1; } } /* * Insert the SAME pointer (not free'd when this entry is * deleted), into another table. * * We want this behaviour because we want OLD names for * the attributes to be read from the configuration * files, but when we're printing them, (and looking up * by value) we want to use the NEW name. */ if (!fr_hash_table_replace(attributes_byvalue, attr)) { librad_log("dict_addattr: Failed inserting attribute name %s", name); return -1; } if (!vendor && (value > 0) && (value < 256)) { dict_base_attrs[value] = attr; } return 0;}/* * Add a value for an attribute to the dictionary. */int dict_addvalue(const char *namestr, const char *attrstr, int value){ size_t length; DICT_ATTR *dattr; DICT_VALUE *dval; static DICT_ATTR *last_attr = NULL; if (!*namestr) { librad_log("dict_addvalue: empty names are not permitted"); return -1; } if ((length = strlen(namestr)) >= DICT_VALUE_MAX_NAME_LEN) { librad_log("dict_addvalue: value name too long"); return -1; } if ((dval = fr_pool_alloc(sizeof(*dval) + length)) == NULL) { librad_log("dict_addvalue: out of memory"); return -1; } memset(dval, 0, sizeof(*dval)); strcpy(dval->name, namestr); dval->value = value; /* * Most VALUEs are bunched together by ATTRIBUTE. We can * save a lot of lookups on dictionary initialization by * caching the last attribute. */ if (last_attr && (strcasecmp(attrstr, last_attr->name) == 0)) { dattr = last_attr; } else { dattr = dict_attrbyname(attrstr); last_attr = dattr; } /* * Remember which attribute is associated with this * value, if possible. */ if (dattr) { if (dattr->flags.has_value_alias) { librad_log("dict_addvalue: Cannot add VALUE for ATTRIBUTE \"%s\": It already has a VALUE-ALIAS", attrstr); return -1; } dval->attr = dattr->attr; /* * Enforce valid values * * Don't worry about fixups... */ switch (dattr->type) { case PW_TYPE_BYTE: if (value > 255) { fr_pool_free(dval); librad_log("dict_addvalue: ATTRIBUTEs of type 'byte' cannot have VALUEs larger than 255"); return -1; } break; case PW_TYPE_SHORT: if (value > 65535) { fr_pool_free(dval); librad_log("dict_addvalue: ATTRIBUTEs of type 'short' cannot have VALUEs larger than 65535"); return -1; } break; /* * Allow octets for now, because * of dictionary.cablelabs */ case PW_TYPE_OCTETS: case PW_TYPE_INTEGER: break; default: fr_pool_free(dval); librad_log("dict_addvalue: VALUEs cannot be defined for attributes of type '%s'", fr_int2str(type_table, dattr->type, "?Unknown?")); return -1; } dattr->flags.has_value = 1; } else { value_fixup_t *fixup; fixup = (value_fixup_t *) malloc(sizeof(*fixup)); if (!fixup) { fr_pool_free(dval); librad_log("dict_addvalue: out of memory"); return -1; } memset(fixup, 0, sizeof(*fixup)); strlcpy(fixup->attrstr, attrstr, sizeof(fixup->attrstr)); fixup->dval = dval; /* * Insert to the head of the list. */ fixup->next = value_fixup; value_fixup = fixup; return 0; } /* * Add the value into the dictionary. */ if (!fr_hash_table_insert(values_byname, dval)) { if (dattr) { DICT_VALUE *old; /* * Suppress duplicates with the same * name and value. There are lots in * dictionary.ascend. */ old = dict_valbyname(dattr->attr, namestr); if (old && (old->value == dval->value)) { fr_pool_free(dval); return 0; } } fr_pool_free(dval); librad_log("dict_addvalue: Duplicate value name %s for attribute %s", namestr, attrstr); return -1; } /* * There are multiple VALUE's, keyed by attribute, so we * take care of that here. */ if (!fr_hash_table_replace(values_byvalue, dval)) { librad_log("dict_addvalue: Failed inserting value %s", namestr); return -1; } return 0;}static int sscanf_i(const char *str, int *pvalue){ int rcode = 0; int base = 10; const char *tab = "0123456789"; if ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) { tab = "0123456789abcdef"; base = 16; str += 2; } while (*str) { const char *c; c = memchr(tab, tolower((int) *str), base); if (!c) return 0; rcode *= base; rcode += (c - tab); str++; } *pvalue = rcode; return 1;}/* * Process the ATTRIBUTE command */static int process_attribute(const char* fn, const int line, const int block_vendor, char **argv, int argc){ int vendor = 0; int value; int type; ATTR_FLAGS flags; if ((argc < 3) || (argc > 4)) { librad_log("dict_init: %s[%d]: invalid ATTRIBUTE line", fn, line); return -1; } /* * Validate all entries */ if (!sscanf_i(argv[1], &value)) { librad_log("dict_init: %s[%d]: invalid value", fn, line); return -1; } /* * find the type of the attribute. */ type = fr_str2int(type_table, argv[2], -1); if (type < 0) { librad_log("dict_init: %s[%d]: invalid type \"%s\"", fn, line, argv[2]); return -1; } /* * Only look up the vendor if the string * is non-empty. */ memset(&flags, 0, sizeof(flags)); if (argc == 4) { char *key, *next, *last; key = argv[3]; do { next = strchr(key, ','); if (next) *(next++) = '\0'; if (strcmp(key, "has_tag") == 0 || strcmp(key, "has_tag=1") == 0) { /* Boolean flag, means this is a tagged attribute */ flags.has_tag = 1; } else if (strncmp(key, "encrypt=", 8) == 0) { /* Encryption method, defaults to 0 (none). Currently valid is just type 2, Tunnel-Password style, which can only be applied to strings. */ flags.encrypt = strtol(key + 8, &last, 0); if (*last) { librad_log( "dict_init: %s[%d] invalid option %s", fn, line, key); return -1; } } else if (strncmp(key, "array", 8) == 0) { flags.array = 1; switch (type) { case PW_TYPE_IPADDR: case PW_TYPE_BYTE: case PW_TYPE_SHORT: case PW_TYPE_INTEGER: case PW_TYPE_DATE: break; default: librad_log( "dict_init: %s[%d] Only IP addresses can have the \"array\" flag set.", fn, line); return -1; } } else if (block_vendor) { librad_log( "dict_init: %s[%d]: unknown option \"%s\"", fn, line, key); return -1; } else { /* Must be a vendor 'flag'... */ if (strncmp(key, "vendor=", 7) == 0) { /* New format */ key += 7; } vendor = dict_vendorbyname(key); if (!vendor) { librad_log( "dict_init: %s[%d]: unknown vendor \"%s\"", fn, line, key); return -1; } if (block_vendor && argv[3][0] && (block_vendor != vendor)) { librad_log("dict_init: %s[%d]: mismatched vendor %s within BEGIN-VENDOR/END-VENDOR block", fn, line, argv[3]); return -1; } } key = next; if (key && !*key) break; } while (key); } if (block_vendor) vendor = block_vendor; /* * Special checks for tags, they make our life much more * difficult. */ if (flags.has_tag) { /* * Only string, octets, and integer can be tagged. */ switch (type) { case PW_TYPE_STRING: case PW_TYPE_INTEGER: break; default: librad_log("dict_init: %s[%d]: Attributes of type %s cannot be tagged.", fn, line, fr_int2str(type_table, type, "?Unknown?")); return -1; } } /* * Add it in. */ if (dict_addattr(argv[0], vendor, type, value, flags) < 0) { librad_log("dict_init: %s[%d]: %s", fn, line, librad_errstr); return -1; } return 0;}/* * Process the VALUE command */static int process_value(const char* fn, const int line, char **argv, int argc){ int value; if (argc != 3) { librad_log("dict_init: %s[%d]: invalid VALUE line", fn, line); return -1; } /* * For Compatibility, skip "Server-Config" */ if (strcasecmp(argv[0], "Server-Config") == 0) return 0; /* * Validate all entries */ if (!sscanf_i(argv[2], &value)) { librad_log("dict_init: %s[%d]: invalid value", fn, line); return -1; } if (dict_addvalue(argv[1], argv[0], value) < 0) { librad_log("dict_init: %s[%d]: %s", fn, line, librad_errstr); return -1; } return 0;}/* * Process the VALUE-ALIAS command * * This allows VALUE mappings to be shared among multiple * attributes. */static int process_value_alias(const char* fn, const int line, char **argv, int argc){ DICT_ATTR *my_da, *da; DICT_VALUE *dval; if (argc != 2) { librad_log("dict_init: %s[%d]: invalid VALUE-ALIAS line", fn, line); return -1; } my_da = dict_attrbyname(argv[0]); if (!my_da) { librad_log("dict_init: %s[%d]: ATTRIBUTE \"%s\" does not exist", fn, line, argv[1]); return -1; } if (my_da->flags.has_value) { librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" with pre-existing VALUE", fn, line, argv[0]); return -1; } if (my_da->flags.has_value_alias) { librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" with pre-existing VALUE-ALIAS", fn, line, argv[0]); return -1; } da = dict_attrbyname(argv[1]); if (!da) { librad_log("dict_init: %s[%d]: Cannot find ATTRIBUTE \"%s\" for alias", fn, line, argv[1]); return -1; } if (!da->flags.has_value) { librad_log("dict_init: %s[%d]: VALUE-ALIAS cannot refer to ATTRIBUTE %s: It has no values", fn, line, argv[1]); return -1; } if (da->flags.has_value_alias) { librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" which itself has a VALUE-ALIAS", fn, line, argv[1]); return -1; } if (my_da->type != da->type) { librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS between attributes of differing type", fn, line); return -1; } if ((dval = fr_pool_alloc(sizeof(*dval))) == NULL) { librad_log("dict_addvalue: out of memory"); return -1; } memset(dval, 0, sizeof(*dval)); dval->name[0] = '\0'; /* empty name */ dval->attr = my_da->attr; dval->value = da->attr; if (!fr_hash_table_insert(values_byname, dval)) { librad_log("dict_init: %s[%d]: Error create alias", fn, line); fr_pool_free(dval); return -1; } return 0;}/* * Process the VENDOR command */static int process_vendor(const char* fn, const int line, char **argv, int argc){ int value; const char *format = NULL; if ((argc < 2) || (argc > 3)) { librad_log( "dict_init: %s[%d] invalid VENDOR entry", fn, line); return -1; } /* * Validate all entries */ if (!isdigit((int) argv[1][0])) { librad_log("dict_init: %s[%d]: invalid value", fn, line); return -1; } value = atoi(argv[1]); /* Create a new VENDOR entry for the list */ if (dict_addvendor(argv[0], value) < 0) { librad_log("dict_init: %s[%d]: %s", fn, line, librad_errstr); return -1; } /* * Look for a format statement */ if (argc == 3) { format = argv[2]; } else if (value == VENDORPEC_USR) { /* catch dictionary screw-ups */ format = "format=4,0"; } else if (value == VENDORPEC_LUCENT) { format = "format=2,1"; } else if (value == VENDORPEC_STARENT) { format = "format=2,2"; } /* else no fixups to do */ if (format) { int type, length; const char *p; DICT_VENDOR *dv; if (strncasecmp(format, "format=", 7) != 0) { librad_log("dict_init: %s[%d]: Invalid format for VENDOR. Expected \"format=\", got \"%s\"", fn, line, format); return -1; } p = format + 7; if ((strlen(p) != 3) || !isdigit((int) p[0]) || (p[1] != ',') ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -