📄 valuepair.c
字号:
(*ptr)++; if (**ptr != 0) *(*ptr)++ = 0; return res;}/* * Turn printable string into time_t * Returns -1 on error, 0 on OK. */static int gettime(const char *valstr, time_t *date){ int i; time_t t; struct tm *tm, s_tm; char buf[64]; char *p; char *f[4]; char *tail = '\0'; /* * Test for unix timestamp date */ *date = strtoul(valstr, &tail, 10); if (*tail == '\0') { return 0; } tm = &s_tm; memset(tm, 0, sizeof(*tm)); tm->tm_isdst = -1; /* don't know, and don't care about DST */ strlcpy(buf, valstr, sizeof(buf)); p = buf; f[0] = mystrtok(&p, " \t"); f[1] = mystrtok(&p, " \t"); f[2] = mystrtok(&p, " \t"); f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */ if (!f[0] || !f[1] || !f[2]) return -1; /* * The time has a colon, where nothing else does. * So if we find it, bubble it to the back of the list. */ if (f[3]) { for (i = 0; i < 3; i++) { if (strchr(f[i], ':')) { p = f[3]; f[3] = f[i]; f[i] = p; break; } } } /* * The month is text, which allows us to find it easily. */ tm->tm_mon = 12; for (i = 0; i < 3; i++) { if (isalpha( (int) *f[i])) { /* * Bubble the month to the front of the list */ p = f[0]; f[0] = f[i]; f[i] = p; for (i = 0; i < 12; i++) { if (strncasecmp(months[i], f[0], 3) == 0) { tm->tm_mon = i; break; } } } } /* month not found? */ if (tm->tm_mon == 12) return -1; /* * The year may be in f[1], or in f[2] */ tm->tm_year = atoi(f[1]); tm->tm_mday = atoi(f[2]); if (tm->tm_year >= 1900) { tm->tm_year -= 1900; } else { /* * We can't use 2-digit years any more, they make it * impossible to tell what's the day, and what's the year. */ if (tm->tm_mday < 1900) return -1; /* * Swap the year and the day. */ i = tm->tm_year; tm->tm_year = tm->tm_mday - 1900; tm->tm_mday = i; } /* * If the day is out of range, die. */ if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) { return -1; } /* * There may be %H:%M:%S. Parse it in a hacky way. */ if (f[3]) { f[0] = f[3]; /* HH */ f[1] = strchr(f[0], ':'); /* find : separator */ if (!f[1]) return -1; *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */ f[2] = strchr(f[1], ':'); /* find : separator */ if (f[2]) { *(f[2]++) = '\0'; /* nuke it, and point to SS */ } else { strcpy(f[2], "0"); /* assignment would discard const */ } tm->tm_hour = atoi(f[0]); tm->tm_min = atoi(f[1]); tm->tm_sec = atoi(f[2]); } /* * Returns -1 on error. */ t = mktime(tm); if (t == (time_t) -1) return -1; *date = t; return 0;}static const char *hextab = "0123456789abcdef";/* * Parse a string value into a given VALUE_PAIR * * FIXME: we probably want to fix this function to accept * octets as values for any type of attribute. We should then * double-check the parsed value, to be sure it's legal for that * type (length, etc.) */VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value){ char *p, *s=0; const char *cp, *cs; int x; size_t length; DICT_VALUE *dval; /* * Even for integers, dates and ip addresses we * keep the original string in vp->vp_strvalue. */ strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue)); vp->length = strlen(vp->vp_strvalue); switch(vp->type) { case PW_TYPE_STRING: /* * Do escaping here */ p = vp->vp_strvalue; cp = value; length = 0; while (*cp && (length < (sizeof(vp->vp_strvalue) - 1))) { char c = *cp++; if (c == '\\') { switch (*cp) { case 'r': c = '\r'; cp++; break; case 'n': c = '\n'; cp++; break; case 't': c = '\t'; cp++; break; case '"': c = '"'; cp++; break; case '\'': c = '\''; cp++; break; case '`': c = '`'; cp++; break; case '\0': c = '\\'; /* no cp++ */ break; default: if ((cp[0] >= '0') && (cp[0] <= '9') && (cp[1] >= '0') && (cp[1] <= '9') && (cp[2] >= '0') && (cp[2] <= '9') && (sscanf(cp, "%3o", &x) == 1)) { c = x; cp += 3; } /* else just do '\\' */ } } *p++ = c; length++; } vp->length = length; break; case PW_TYPE_IPADDR: /* * It's a comparison, not a real IP. */ if ((vp->operator == T_OP_REG_EQ) || (vp->operator == T_OP_REG_NE)) { break; } /* * FIXME: complain if hostname * cannot be resolved, or resolve later! */ s = NULL; if ((p = strrchr(value, '+')) != NULL && !p[1]) { cs = s = strdup(value); if (!s) return NULL; p = strrchr(s, '+'); *p = 0; vp->flags.addport = 1; } else { p = NULL; cs = value; } { fr_ipaddr_t ipaddr; if (ip_hton(cs, AF_INET, &ipaddr) < 0) { free(s); librad_log("Failed to find IP address for %s", cs); return NULL; } vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr; } free(s); vp->length = 4; break; case PW_TYPE_BYTE: if (value && (value[0] == '0') && (value[1] == 'x')) { goto do_octets; } /* * Note that ALL integers are unsigned! */ vp->vp_integer = (uint32_t) strtoul(value, &p, 10); if (!*p) { if (vp->vp_integer > 255) { librad_log("Byte value \"%s\" is larger than 255", value); return NULL; } vp->length = 1; break; } /* * Look for the named value for the given * attribute. */ if ((dval = dict_valbyname(vp->attribute, value)) == NULL) { librad_log("Unknown value %s for attribute %s", value, vp->name); return NULL; } vp->vp_integer = dval->value; vp->length = 1; break; case PW_TYPE_SHORT: /* * Note that ALL integers are unsigned! */ vp->vp_integer = (uint32_t) strtoul(value, &p, 10); if (!*p) { if (vp->vp_integer > 65535) { librad_log("Byte value \"%s\" is larger than 65535", value); return NULL; } vp->length = 2; break; } /* * Look for the named value for the given * attribute. */ if ((dval = dict_valbyname(vp->attribute, value)) == NULL) { librad_log("Unknown value %s for attribute %s", value, vp->name); return NULL; } vp->vp_integer = dval->value; vp->length = 2; break; case PW_TYPE_INTEGER: /* * Note that ALL integers are unsigned! */ vp->vp_integer = (uint32_t) strtoul(value, &p, 10); if (!*p) { vp->length = 4; break; } /* * Look for the named value for the given * attribute. */ if ((dval = dict_valbyname(vp->attribute, value)) == NULL) { librad_log("Unknown value %s for attribute %s", value, vp->name); return NULL; } vp->vp_integer = dval->value; vp->length = 4; break; case PW_TYPE_DATE: { /* * time_t may be 64 bits, whule vp_date * MUST be 32-bits. We need an * intermediary variable to handle * the conversions. */ time_t date; if (gettime(value, &date) < 0) { librad_log("failed to parse time string " "\"%s\"", value); return NULL; } vp->vp_date = date; } vp->length = 4; break; case PW_TYPE_ABINARY:#ifdef ASCEND_BINARY if (strncasecmp(value, "0x", 2) == 0) { vp->type = PW_TYPE_OCTETS; goto do_octets; } 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 do_octets: /* raw octets: 0x01020304... */ case PW_TYPE_OCTETS: if (strncasecmp(value, "0x", 2) == 0) { uint8_t *us; cp = value + 2; us = vp->vp_octets; 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++; } } break; case PW_TYPE_IFID: if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) { librad_log("failed to parse interface-id " "string \"%s\"", value); return NULL; } vp->length = 8; break; case PW_TYPE_IPV6ADDR: if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) <= 0) { librad_log("failed to parse IPv6 address " "string \"%s\"", value); return NULL; } vp->length = 16; /* length of IPv6 address */ break; case PW_TYPE_IPV6PREFIX: p = strchr(value, '/'); if (!p || ((p - value) >= 256)) { librad_log("invalid IPv6 prefix " "string \"%s\"", value); return NULL; } else { unsigned int prefix; char buffer[256], *eptr; memcpy(buffer, value, p - value); buffer[p - value] = '\0'; if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) { librad_log("failed to parse IPv6 address " "string \"%s\"", value); return NULL; } prefix = strtoul(p + 1, &eptr, 10); if ((prefix > 128) || *eptr) { librad_log("failed to parse IPv6 address " "string \"%s\"", value); return NULL; } vp->vp_octets[1] = prefix; } vp->vp_octets[0] = '\0'; vp->length = 16 + 2; break; case PW_TYPE_ETHERNET: { const char *c1, *c2; length = 0; cp = value; while (*cp) { if (cp[1] == ':') { c1 = hextab; c2 = memchr(hextab, tolower((int) cp[0]), 16); cp += 2; } else if ((cp[1] != '\0') && ((cp[2] == ':') || (cp[2] == '\0'))) { c1 = memchr(hextab, tolower((int) cp[0]), 16); c2 = memchr(hextab, tolower((int) cp[1]), 16); cp += 2; if (*cp == ':') cp++; } else { c1 = c2 = NULL; } if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) { librad_log("failed to parse Ethernet address \"%s\"", value); return NULL; } vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab); length++; } } vp->length = 6; 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 * VendorName-Attr-%d */static VALUE_PAIR *pairmake_any(const char *attribute, const char *value, int operator){ int attr, vendor; size_t size; const char *p = attribute; char *q; VALUE_PAIR *vp; /* * Unknown attributes MUST be of type 'octets' */ if (value && (strncasecmp(value, "0x", 2) != 0)) { librad_log("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute); return NULL; } attr = vendor = 0; /* * Pull off vendor prefix first. */ if (strncasecmp(p, "Attr-", 5) != 0) { if (strncasecmp(p, "Vendor-", 7) == 0) { vendor = (int) strtol(p + 7, &q, 10); if ((vendor == 0) || (vendor > 65535)) { librad_log("Invalid vendor value in attribute name \"%s\"", attribute); return NULL; } p = q; } else { /* must be vendor name */ char buffer[256]; q = strchr(p, '-'); if (!q) { librad_log("Invalid vendor name in attribute name \"%s\"", attribute); return NULL; } if ((size_t) (q - p) >= sizeof(buffer)) { librad_log("Vendor name too long in attribute name \"%s\"", attribute); return NULL; } memcpy(buffer, p, (q - p)); buffer[q - p] = '\0'; vendor = dict_vendorbyname(buffer); if (!vendor) { librad_log("Unknown vendor name in attribute name \"%s\"", attribute); return NULL; } p = q; } if (*p != '-') { librad_log("Invalid text following vendor definition in attribute name \"%s\"", attribute); return NULL; } p++; } /* * Attr-%d */ if (strncasecmp(p, "Attr-", 5) != 0) { librad_log("Invalid format in attribute name \"%s\"", attribute); return NULL; } attr = strtol(p + 5, &q, 10); /* * Invalid, or trailing text after number. */ if ((attr == 0) || *q) { librad_log("Invalid value in attribute name \"%s\"", attribute); return NULL; } /* * Double-check the size of attr. */ if (vendor) { DICT_VENDOR *dv = dict_vendorbyvalue(vendor); if (!dv) { if (attr > 255) { attr_error: librad_log("Invalid attribute number in attribute name \"%s\"", attribute); return NULL; } } else switch (dv->type) { case 1: if (attr > 255) goto attr_error; break; case 2: if (attr > 65535) goto attr_error; break; case 4: /* Internal limitations! */ if (attr > 65535) goto attr_error; break; default: librad_log("Internal sanity check failed"); return NULL; } } attr |= vendor << 16; /* * We've now parsed the attribute properly, Let's create * it. This next stop also looks the attribute up in the * dictionary, and creates the appropriate type for it. */ if ((vp = paircreate(attr, PW_TYPE_OCTETS)) == NULL) { librad_log("out of memory");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -