]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add IPv4prefix data type for RFC 6572
authorAlan T. DeKok <aland@freeradius.org>
Thu, 20 Dec 2012 14:18:41 +0000 (09:18 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 20 Dec 2012 14:44:09 +0000 (09:44 -0500)
share/dictionary.rfc6572
src/include/libradius.h
src/include/radius.h
src/lib/dict.c
src/lib/print.c
src/lib/radius.c
src/lib/valuepair.c

index be10316cecfa919bcd5bc3f9a19da26b310a308e..d30f328522d1db8521b17f4348599b467f955ea2 100644 (file)
@@ -17,10 +17,8 @@ ATTRIBUTE    PMIP6-Home-HN-Prefix                    151     ipv6prefix
 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
index bd8e9d15ca73ec3a839d088ac5424d8c304584d8..41c50db456b65271c75f4b0f8034d071b6ea9045 100644 (file)
@@ -170,6 +170,7 @@ typedef union value_pair_data {
        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;
@@ -206,6 +207,7 @@ typedef struct value_pair {
 #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
index 9fe596e6c739014c1667651cbef4bb15f8128f9e..02842b2e73427ff7519c5142a95f1e956a7645c4 100644 (file)
@@ -25,6 +25,7 @@
 #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)
 
index e225451d375e95d1babeca17ef19dd323e6464e5..0a7af5c2799381869d9932552a9d64cb30bdf913 100644 (file)
@@ -108,6 +108,7 @@ const FR_NAME_NUMBER dict_attr_types[] = {
        { "int32",      PW_TYPE_SIGNED },
        { "integer64",  PW_TYPE_INTEGER64 },
        { "uint64",     PW_TYPE_INTEGER64 },
+       { "ipv4prefix", PW_TYPE_IPV4PREFIX },
        { NULL, 0 }
 };
 
index c36e0477060c2d7b248d73cb41301226cb2b1649..81e29ea537bbff664da8522a9c10ea173aecd06e 100644 (file)
@@ -334,6 +334,24 @@ int vp_prints_value(char * out, size_t outlen, const VALUE_PAIR *vp, int delimit
                }
                        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],
index a7c7fa3c51befce144a0d8df14a34563dd040d55..ae7801921f35bd4d617b042b69aa5a9d7f4e4503 100644 (file)
@@ -848,6 +848,7 @@ static ssize_t vp2data_any(const RADIUS_PACKET *packet,
        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;
@@ -3082,6 +3083,14 @@ static ssize_t data2vp_any(const RADIUS_PACKET *packet,
                }
                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;
 
@@ -3901,6 +3910,7 @@ ssize_t rad_vp2data(const VALUE_PAIR *vp, uint8_t *out, size_t outlen)
                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:
index 918b9d28e9eab1962a059dee2ad842d1a3600d1f..7b79f6eb7e426665774f17139f26ed525cf8d106 100644 (file)
@@ -130,6 +130,10 @@ VALUE_PAIR *pairalloc(const DICT_ATTR *da)
                        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;
@@ -1202,10 +1206,54 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                                }
                                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;
@@ -2164,6 +2212,14 @@ int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
                                 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));