📄 valuepair.c
字号:
* Already handled above. */ break; case PW_TYPE_IPADDR: /* * FIXME: complain if hostname * cannot be resolved, or resolve later! */ if ((p = strrchr(value, '+')) != NULL && !p[1]) { cs = s = strdup(value); p = strrchr(s, '+'); *p = 0; vp->flags.addport = 1; } else { p = NULL; cs = value; } vp->lvalue = librad_dodns ? ip_getaddr(cs) : ip_addr(cs); if (s) free(s); vp->length = 4; break; case PW_TYPE_INTEGER: /* * If it starts with a digit, it must * be a number (or a range). * * Note that ALL integers are unsigned! */ if (isdigit((int) *value)) { vp->lvalue = (uint32_t) strtoul(value, NULL, 10); vp->length = 4; } /* * Look for the named value for the given * attribute. */ else if ((dval = dict_valbyname(vp->attribute, value)) == NULL) { librad_log("Unknown value %s for attribute %s", value, vp->name); return NULL; } else { vp->lvalue = dval->value; vp->length = 4; } break; case PW_TYPE_DATE: if (gettime(value, (time_t *)&vp->lvalue) < 0) { librad_log("failed to parse time string " "\"%s\"", value); return NULL; } vp->length = 4; break; case PW_TYPE_ABINARY:#ifdef ASCEND_BINARY /* * Special case to convert filter to binary */ strNcpy(vp->strvalue, value, sizeof(vp->strvalue)); if (ascend_parse_filter(vp) < 0 ) { librad_log("failed to parse Ascend binary attribute: %s", librad_errstr); return NULL; } break; /* * If Ascend binary is NOT defined, * then fall through to raw octets, so that * the user can at least make them by hand... */#endif /* raw octets: 0x01020304... */ case PW_TYPE_OCTETS: if (strncasecmp(value, "0x", 2) == 0) { u_char *us; cp = value + 2; us = vp->strvalue; vp->length = 0; /* * There is only one character, * die. */ if ((strlen(cp) & 0x01) != 0) { librad_log("Hex string is not an even length string."); return NULL; } while (*cp && vp->length < MAX_STRING_LEN) { unsigned int tmp; if (sscanf(cp, "%02x", &tmp) != 1) { librad_log("Non-hex characters at %c%c", cp[0], cp[1]); return NULL; } cp += 2; *(us++) = tmp; vp->length++; } *us = '\0'; } break; case PW_TYPE_IFID: if (ifid_aton(value, vp->strvalue) == NULL) { librad_log("failed to parse interface-id " "string \"%s\"", value); return NULL; } vp->length = 8; vp->strvalue[vp->length] = '\0'; break; case PW_TYPE_IPV6ADDR: if (ipv6_addr(value, vp->strvalue) < 0) { librad_log("failed to parse IPv6 address " "string \"%s\"", value); return NULL; } vp->length = 16; /* length of IPv6 address */ vp->strvalue[vp->length] = '\0'; break; /* * Anything else. */ default: librad_log("unknown attribute type %d", vp->type); return NULL; } return vp;}/* * Create a VALUE_PAIR from an ASCII attribute and value, * where the attribute name is in the form: * * Attr-%d * Vendor-%d-Attr-%d */static VALUE_PAIR *pairmake_any(const char *attribute, const char *value, int operator){ int attr; const char *p; VALUE_PAIR *vp; DICT_ATTR *da; /* * Unknown attributes MUST be of type 'octets' */ if (value && (strncasecmp(value, "0x", 2) != 0)) { goto error; } /* * Attr-%d */ if (strncasecmp(attribute, "Attr-", 5) == 0) { attr = atoi(attribute + 5); p = attribute + 5; p += strspn(p, "0123456789"); if (*p != 0) goto error; /* * Vendor-%d-Attr-%d */ } else if (strncasecmp(attribute, "Vendor-", 7) == 0) { int vendor; vendor = atoi(attribute + 7); if ((vendor == 0) || (vendor > 65535)) goto error; p = attribute + 7; p += strspn(p, "0123456789"); /* * Not Vendor-%d-Attr-%d */ if (strncasecmp(p, "-Attr-", 6) != 0) goto error; p += 6; attr = atoi(p); p += strspn(p, "0123456789"); if (*p != 0) goto error; if ((attr == 0) || (attr > 65535)) goto error; attr |= (vendor << 16); /* * VendorName-Attr-%d */ } else if (((p = strchr(attribute, '-')) != NULL) && (strncasecmp(p, "-Attr-", 6) == 0)) { int vendor; char buffer[256]; if ((p - attribute) >= sizeof(buffer)) goto error; memcpy(buffer, attribute, p - attribute); buffer[p - attribute] = '\0'; vendor = dict_vendorbyname(buffer); if (vendor == 0) goto error; p += 6; attr = atoi(p); p += strspn(p, "0123456789"); if (*p != 0) goto error; if ((attr == 0) || (attr > 65535)) goto error; attr |= (vendor << 16); } else { /* very much unknown: die */ error: librad_log("Unknown attribute \"%s\"", attribute); return NULL; } /* * We've now parsed the attribute properly, and verified * it to have value 'octets'. Let's create it. */ if ((vp = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == NULL) { librad_log("out of memory"); return NULL; } memset(vp, 0, sizeof(VALUE_PAIR)); vp->type = PW_TYPE_OCTETS; /* * It may not be valid hex characters. If not, die. */ if (pairparsevalue(vp, value) == NULL) { pairfree(&vp); return NULL; } /* * Dictionary type over-rides what the caller says. * This "converts" the parsed value into the appropriate * type. * * Also, normalize the name of the attribute... * * Much of this code is copied from paircreate() */ if ((da = dict_attrbyvalue(attr)) != NULL) { strcpy(vp->name, da->name); vp->type = da->type; vp->flags = da->flags; /* * Sanity check the type for length. We don't * want to look at attributes which are of the * wrong length. */ switch (vp->type) { case PW_TYPE_DATE: case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: /* always kept in network byte order */ if (vp->length != 4) { length_error: pairfree(&vp); librad_log("Attribute has invalid length"); return NULL; } memcpy(&vp->lvalue, vp->strvalue, sizeof(vp->lvalue)); break; case PW_TYPE_IFID: if (vp->length != 8) goto length_error; break; case PW_TYPE_IPV6ADDR: if (vp->length != 16) goto length_error; break;#ifdef ASCEND_BINARY case PW_TYPE_ABINARY: if (vp->length != 32) goto length_error; break;#endif default: /* string, octets, etc. */ break; } } else if (VENDOR(attr) == 0) { sprintf(vp->name, "Attr-%u", attr); } else { sprintf(vp->name, "Vendor-%u-Attr-%u", VENDOR(attr), attr & 0xffff); } vp->attribute = attr; vp->operator = (operator == 0) ? T_OP_EQ : operator; vp->next = NULL; return vp;}/* * Create a VALUE_PAIR from an ASCII attribute and value. */VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator){ DICT_ATTR *da; VALUE_PAIR *vp; char *tc, *ts; signed char tag; int found_tag;#ifdef HAVE_REGEX_H int res; regex_t cre;#endif /* * Check for tags in 'Attribute:Tag' format. */ found_tag = 0; tag = 0; ts = strrchr( attribute, ':' ); if (ts && ts[1]) { /* Colon found with something behind it */ if (ts[1] == '*' && ts[2] == 0) { /* Wildcard tag for check items */ tag = TAG_ANY; *ts = 0; } else if ((ts[1] >= '0') && (ts[1] <= '9')) { /* It's not a wild card tag */ tag = strtol(ts + 1, &tc, 0); if (tc && !*tc && TAG_VALID_ZERO(tag)) *ts = 0; else tag = 0; } else { librad_log("Invalid tag for attribute %s", attribute); return NULL; } found_tag = 1; } /* * It's not found in the dictionary, so we use * another method to create the attribute. */ if ((da = dict_attrbyname(attribute)) == NULL) { return pairmake_any(attribute, value, operator); } if ((vp = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == NULL) { librad_log("out of memory"); return NULL; } memset(vp, 0, sizeof(VALUE_PAIR)); vp->attribute = da->attr; vp->type = da->type; vp->operator = (operator == 0) ? T_OP_EQ : operator; strcpy(vp->name, da->name); vp->flags = da->flags; vp->next = NULL; /* Check for a tag in the 'Merit' format of: * :Tag:Value. Print an error if we already found * a tag in the Attribute. */ if (value && (*value == ':' && da->flags.has_tag)) { /* If we already found a tag, this is invalid */ if(found_tag) { pairbasicfree(vp); librad_log("Duplicate tag %s for attribute %s", value, vp->name); DEBUG("Duplicate tag %s for attribute %s\n", value, vp->name); return NULL; } /* Colon found and attribute allows a tag */ if (value[1] == '*' && value[2] == ':') { /* Wildcard tag for check items */ tag = TAG_ANY; value += 3; } else { /* Real tag */ tag = strtol(value + 1, &tc, 0); if (tc && *tc==':' && TAG_VALID_ZERO(tag)) value = tc + 1; else tag = 0; } found_tag = 1; } if (found_tag) { vp->flags.tag = tag; } switch (vp->operator) { default: break; /* * For =* and !* operators, the value is irrelevant * so we return now. */ case T_OP_CMP_TRUE: case T_OP_CMP_FALSE: vp->strvalue[0] = '\0'; vp->length = 0; return vp; break; /* * Regular expression comparison of integer attributes * does a STRING comparison of the names of their * integer attributes. */ case T_OP_REG_EQ: /* =~ */ case T_OP_REG_NE: /* !~ */ if (vp->type == PW_TYPE_INTEGER) { return vp; }#ifdef HAVE_REGEX_H /* * Regular expression match with no regular * expression is wrong. */ if (!value) { pairfree(&vp); return NULL; } res = regcomp(&cre, value, REG_EXTENDED|REG_NOSUB); if (res != 0) { char msg[128]; regerror(res, &cre, msg, sizeof(msg)); librad_log("Illegal regular expression in attribute: %s: %s", vp->name, msg); pairbasicfree(vp); return NULL; } regfree(&cre);#else librad_log("Regelar expressions not enabled in this build, error in attribute %s", vp->name); pairbasicfree(vp); return NULL;#endif } if (value && (pairparsevalue(vp, value) == NULL)) { pairbasicfree(vp); return NULL; } return vp;}/* * Read a valuepair from a buffer, and advance pointer. * Sets *eol to T_EOL if end of line was encountered. */VALUE_PAIR *pairread(char **ptr, LRAD_TOKEN *eol){ char buf[64]; char attr[64]; char value[256]; char *p; LRAD_TOKEN token, t, xlat; VALUE_PAIR *vp; *eol = T_INVALID; /* Get attribute. */ token = gettoken(ptr, attr, sizeof(attr)); /* If it's a comment, then exit, as we haven't read a pair */ if (token == T_HASH) { *eol = token; librad_log("Read a comment instead of a token"); return NULL; } /* It's not a comment, so it MUST be an attribute */ if ((token == T_EOL) || (attr[0] == 0)) { librad_log("No token read where we expected an attribute name"); return NULL; } /* Now we should have an '=' here. */ token = gettoken(ptr, buf, sizeof(buf)); if (token < T_EQSTART || token > T_EQEND) { librad_log("expecting '='"); return NULL; } /* Read value. Note that empty string values are allowed */ xlat = gettoken(ptr, value, sizeof(value)); if (xlat == T_EOL) { librad_log("failed to get value"); return NULL; } /* * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH */ p = *ptr; t = gettoken(&p, buf, sizeof(buf)); if (t != T_EOL && t != T_COMMA && t != T_HASH) { librad_log("Expected end of line or comma"); return NULL; } *eol = t; if (t == T_COMMA) { *ptr = p; } switch (xlat) { /* * Make the full pair now. */ default: vp = pairmake(attr, value, token); break; /* * Perhaps do xlat's */ case T_DOUBLE_QUOTED_STRING: p = strchr(value, '%'); if (p && (p[1] == '{')) { vp = pairmake(attr, NULL, token); if (!vp) { *eol = T_INVALID; return NULL; } strNcpy(vp->strvalue, value, sizeof(vp->strvalue)); vp->flags.do_xlat = 1; vp->length = 0; } else { vp = pairmake(attr, value, token); } break; /* * Mark the pair to be allocated later. */ case T_BACK_QUOTED_STRING: vp = pairmake(attr, NULL, token); if (!vp) { *eol = T_INVALID; return NULL; } vp->flags.do_xlat = 1; strNcpy(vp->strvalue, value, sizeof(vp->strvalue)); vp->length = 0; break; } return vp;}/* * Read one line of attribute/value pairs. This might contain * multiple pairs seperated by comma's. */LRAD_TOKEN userparse(char *buffer, VALUE_PAIR **first_pair){ VALUE_PAIR *vp; char *p; LRAD_TOKEN last_token = T_INVALID; LRAD_TOKEN previous_token; /* * We allow an empty line. */ if (buffer[0] == 0) return T_EOL; p = buffer; do { previous_token = last_token; if ((vp = pairread(&p, &last_token)) == NULL) { return last_token; } pairadd(first_pair, vp); } while (*p && (last_token == T_COMMA)); /* * Don't tell the caller that there was a comment. */ if (last_token == T_HASH) { return previous_token; } /* * And return the last token which we read. */ return last_token;}/* * Read valuepairs from the fp up to End-Of-File. * * Hmm... this function is only used by radclient.. */VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix){ char buf[8192]; LRAD_TOKEN last_token = T_EOL; VALUE_PAIR *vp; VALUE_PAIR *list; int error = 0; list = NULL; while (!error && fgets(buf, sizeof(buf), fp) != NULL) { /* * If we get a '\n' by itself, we assume that's * the end of that VP */ if ((buf[0] == '\n') && (list)) { return list; } if ((buf[0] == '\n') && (!list)) { continue; } /* * Comments get ignored */ if (buf[0] == '#') continue; /* * Read all of the attributes on the current line. */ vp = NULL; last_token = userparse(buf, &vp); if (!vp) { if (last_token != T_EOL) { librad_perror(errprefix); error = 1; break; } break; } pairadd(&list, vp); buf[0] = '\0'; } if (error) pairfree(&list); *pfiledone = 1; return error ? NULL: list;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -