ATTRIBUTE PMIP6-Visited-HN-Prefix 152 ipv6prefix
ATTRIBUTE PMIP6-Home-Interface-ID 153 ifid
ATTRIBUTE PMIP6-Visited-Interface-ID 154 ifid
-# ipv4 prefix?
-ATTRIBUTE PMIP6-Home-IPv4-HoA 155 octets
-# ipv4 prefix?
-ATTRIBUTE PMIP6-Visited-IPv4-HoA 156 octets
+ATTRIBUTE PMIP6-Home-IPv4-HoA 155 ipv4prefix
+ATTRIBUTE PMIP6-Visited-IPv4-HoA 156 ipv4prefix
ATTRIBUTE PMIP6-Home-DHCP4-Server-Address 157 ipaddr
ATTRIBUTE PMIP6-Visited-DHCP4-Server-Address 158 ipaddr
ATTRIBUTE PMIP6-Home-DHCP6-Server-Address 159 ipv6addr
uint8_t filter[32];
uint8_t ifid[8]; /* struct? */
uint8_t ipv6prefix[18]; /* struct? */
+ uint8_t ipv4prefix[6]; /* struct? */
uint8_t ether[6];
uint8_t *tlv;
} VALUE_PAIR_DATA;
#define vp_ipv6addr data.ipv6addr
#define vp_ifid data.ifid
#define vp_ipv6prefix data.ipv6prefix
+#define vp_ipv4prefix data.ipv4prefix
#define vp_filter data.filter
#define vp_ether data.ether
#define vp_signed data.sinteger
#define PW_TYPE_LONG_EXTENDED 16
#define PW_TYPE_EVS 17
#define PW_TYPE_INTEGER64 18
+#define PW_TYPE_IPV4PREFIX 19
#define PW_FLAG_LONG (1 << 8)
{ "int32", PW_TYPE_SIGNED },
{ "integer64", PW_TYPE_INTEGER64 },
{ "uint64", PW_TYPE_INTEGER64 },
+ { "ipv4prefix", PW_TYPE_IPV4PREFIX },
{ NULL, 0 }
};
}
break;
+ case PW_TYPE_IPV4PREFIX:
+ {
+ struct in_addr addr;
+
+ /*
+ * Alignment issues.
+ */
+ memcpy(&addr, &(vp->vp_ipv4prefix[2]), sizeof(addr));
+
+ a = inet_ntop(AF_INET, &addr, buf, sizeof(buf));
+ if (a) {
+ char *p = buf + strlen(buf);
+ snprintf(p, buf + sizeof(buf) - p - 1, "/%u",
+ (unsigned int) (vp->vp_octets[1] & 0x3f));
+ }
+ }
+ break;
+
case PW_TYPE_ETHERNET:
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
vp->vp_ether[0], vp->vp_ether[1],
case PW_TYPE_IFID:
case PW_TYPE_IPV6ADDR:
case PW_TYPE_IPV6PREFIX:
+ case PW_TYPE_IPV4PREFIX:
case PW_TYPE_ABINARY:
/* nothing more to do */
break;
}
break;
+ case PW_TYPE_IPV4PREFIX:
+ if (vp->length != sizeof(vp->vp_ipv4prefix)) goto raw;
+
+ if ((buffer[1] & 0x3f) > 32) goto raw;
+
+ memcpy(&vp->vp_ipv4prefix, buffer, sizeof(vp->vp_ipv4prefix));
+ break;
+
case PW_TYPE_SIGNED:
if (vp->length != 4) goto raw;
case PW_TYPE_IPADDR:
case PW_TYPE_IPV6ADDR:
case PW_TYPE_IPV6PREFIX:
+ case PW_TYPE_IPV4PREFIX:
case PW_TYPE_ABINARY:
case PW_TYPE_TLV:
do_raw:
vp->length = sizeof(vp->vp_ipv6prefix);
break;
+ case PW_TYPE_IPV4PREFIX:
+ vp->length = sizeof(vp->vp_ipv4prefix);
+ break;
+
case PW_TYPE_ETHERNET:
vp->length = sizeof(vp->vp_ether);
break;
}
vp->vp_octets[1] = prefix;
}
- vp->vp_octets[0] = '\0';
+ vp->vp_octets[0] = 0;
vp->length = 16 + 2;
break;
+ case PW_TYPE_IPV4PREFIX:
+ p = strchr(value, '/');
+ if (!p || ((p - value) >= 256)) {
+ fr_strerror_printf("invalid IPv4 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_INET, buffer, vp->vp_octets + 2) <= 0) {
+ fr_strerror_printf("failed to parse IPv6 address "
+ "string \"%s\"", value);
+ return NULL;
+ }
+
+ prefix = strtoul(p + 1, &eptr, 10);
+ if ((prefix > 32) || *eptr) {
+ fr_strerror_printf("failed to parse IPv6 address "
+ "string \"%s\"", value);
+ return NULL;
+ }
+ vp->vp_octets[1] = prefix;
+
+ if (prefix < 32) {
+ uint32_t addr, mask;
+
+ memcpy(&addr, vp->vp_octets + 2, sizeof(addr));
+ mask = 1;
+ mask <<= (32 - prefix);
+ mask--;
+ mask = ~mask;
+ mask = htonl(mask);
+ addr &= mask;
+ memcpy(vp->vp_octets + 2, &addr, sizeof(addr));
+ }
+ }
+ vp->vp_octets[0] = 0;
+ vp->length = 8;
+ break;
+
case PW_TYPE_ETHERNET:
{
const char *c1, *c2;
sizeof(two->vp_ipv6prefix));
break;
+ /*
+ * FIXME: do a smarter comparison...
+ */
+ case PW_TYPE_IPV4PREFIX:
+ compare = memcmp(&two->vp_ipv4prefix, &one->vp_ipv4prefix,
+ sizeof(two->vp_ipv4prefix));
+ break;
+
case PW_TYPE_IFID:
compare = memcmp(&two->vp_ifid, &one->vp_ifid,
sizeof(two->vp_ifid));