+ 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))) {
+ fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
+ return NULL;
+ }
+ vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
+ length++;
+ }
+ }
+ vp->length = 6;
+ break;
+
+ case PW_TYPE_COMBO_IP:
+ if (inet_pton(AF_INET6, value, vp->vp_strvalue) > 0) {
+ vp->type = PW_TYPE_IPV6ADDR;
+ vp->length = 16; /* length of IPv6 address */
+ vp->vp_strvalue[vp->length] = '\0';
+
+ } else {
+ fr_ipaddr_t ipaddr;
+
+ if (ip_hton(value, AF_INET, &ipaddr) < 0) {
+ fr_strerror_printf("Failed to find IPv4 address for %s", value);
+ return NULL;
+ }
+
+ vp->type = PW_TYPE_IPADDR;
+ vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
+ vp->length = 4;
+ }
+ break;
+
+ case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
+ vp->vp_signed = (int32_t) strtol(value, &p, 10);
+ vp->length = 4;
+ break;
+
+ case PW_TYPE_TLV: /* don't use this! */
+ if (strncasecmp(value, "0x", 2) != 0) {
+ fr_strerror_printf("Invalid TLV specification");
+ return NULL;
+ }
+ length = strlen(value + 2) / 2;
+ if (vp->length < length) {
+ free(vp->vp_tlv);
+ vp->vp_tlv = NULL;
+ }
+ vp->vp_tlv = malloc(length);
+ if (!vp->vp_tlv) {
+ fr_strerror_printf("No memory");
+ return NULL;
+ }
+ if (fr_hex2bin(value + 2, vp->vp_tlv,
+ length) != length) {
+ fr_strerror_printf("Invalid hex data in TLV");
+ return NULL;
+ }
+ vp->length = length;
+ break;
+
+ /*
+ * Anything else.
+ */