From 3ba4a62187f86320f821de2feed468d9e7eb24fb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 30 May 2014 21:27:56 +0100 Subject: [PATCH] Add PW_TYPE_COMBO_IP_PREFIX (conffile parser only) Change 'ipaddr' to PW_TYPE_COMBO_IP_PREFIX so we can be really lazy about IP formats --- src/include/conffile.h | 6 ++- src/include/radius.h | 1 + src/lib/radius.c | 1 + src/lib/valuepair.c | 1 + src/main/client.c | 3 +- src/main/conffile.c | 101 ++++++++++++++++++++++++----------------- 6 files changed, 69 insertions(+), 44 deletions(-) diff --git a/src/include/conffile.h b/src/include/conffile.h index 37cb87053ffd..dbfd0593a165 100644 --- a/src/include/conffile.h +++ b/src/include/conffile.h @@ -72,14 +72,18 @@ typedef struct timeval _timeval_t; __builtin_choose_expr(__builtin_types_compatible_p(uint8_t[6], _ct), _p, (conf_type_mismatch) 0),\ __builtin_choose_expr((_t == PW_TYPE_SIGNED),\ __builtin_choose_expr(__builtin_types_compatible_p(int32_t *, _ct), _p, (conf_type_mismatch) 0),\ + __builtin_choose_expr((_t == PW_TYPE_COMBO_IP),\ + __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ __builtin_choose_expr((_t == PW_TYPE_INTEGER64),\ __builtin_choose_expr(__builtin_types_compatible_p(uint64_t *, _ct), _p, (conf_type_mismatch) 0),\ __builtin_choose_expr((_t == PW_TYPE_IPV4PREFIX),\ __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ __builtin_choose_expr((_t == PW_TYPE_TIMEVAL),\ __builtin_choose_expr(__builtin_types_compatible_p(_timeval_t *, _ct), _p, (conf_type_mismatch) 0),\ + __builtin_choose_expr((_t == PW_TYPE_COMBO_IPPREFIX),\ + __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ (conf_type_invalid) 0\ - )))))))))))))))))) + )))))))))))))))))))) # define FR_CONF_OFFSET(_t, _s, _f) _t, FR_CONF_TYPE_CHECK(((_t) & 0xff), __typeof__(&(((_s *)NULL)->_f)), offsetof(_s, _f)), NULL # define FR_CONF_POINTER(_t, _p) _t, 0, FR_CONF_TYPE_CHECK(((_t) & 0xff), __typeof__(_p), _p) diff --git a/src/include/radius.h b/src/include/radius.h index a83c0bb304b0..35ce8e71b50f 100644 --- a/src/include/radius.h +++ b/src/include/radius.h @@ -30,6 +30,7 @@ typedef enum { PW_TYPE_VSA, //!< Vendor-Specific, for RADIUS attribute 26. PW_TYPE_TIMEVAL, //!< Time value (struct timeval), only for config items. PW_TYPE_BOOLEAN, //!< A truth value. + PW_TYPE_COMBO_IPPREFIX, //!< WiMAX IPv4 or IPv6 address prefix depending on length. PW_TYPE_MAX //!< Number of defined data types. } PW_TYPE; diff --git a/src/lib/radius.c b/src/lib/radius.c index 53246368ce5c..f496fa351923 100644 --- a/src/lib/radius.c +++ b/src/lib/radius.c @@ -3999,6 +3999,7 @@ ssize_t rad_vp2data(uint8_t const **out, VALUE_PAIR const *vp) case PW_TYPE_ABINARY: case PW_TYPE_ETHERNET: case PW_TYPE_COMBO_IP: + case PW_TYPE_COMBO_IPPREFIX: { void const *p = &vp->data; memcpy(out, &p, sizeof(*out)); diff --git a/src/lib/valuepair.c b/src/lib/valuepair.c index ba0a98e7f132..0fa98d73505a 100644 --- a/src/lib/valuepair.c +++ b/src/lib/valuepair.c @@ -2445,6 +2445,7 @@ int8_t paircmp_value(VALUE_PAIR const *one, VALUE_PAIR const *two) */ case PW_TYPE_INVALID: /* We should never see these */ case PW_TYPE_COMBO_IP: /* This should of been converted into IPADDR/IPV6ADDR */ + case PW_TYPE_COMBO_IPPREFIX: /* This should of been converted into IPADDR/IPV6ADDR */ case PW_TYPE_TLV: case PW_TYPE_EXTENDED: case PW_TYPE_LONG_EXTENDED: diff --git a/src/main/client.c b/src/main/client.c index e68c38ab967d..124adaabb2de 100644 --- a/src/main/client.c +++ b/src/main/client.c @@ -426,7 +426,8 @@ static CONF_PARSER limit_config[] = { #endif static const CONF_PARSER client_config[] = { - { "ipaddr", FR_CONF_POINTER(PW_TYPE_IPV4PREFIX, &cl_ipaddr), NULL }, + { "ipaddr", FR_CONF_POINTER(PW_TYPE_COMBO_IPPREFIX, &cl_ipaddr), NULL }, + { "ipv4addr", FR_CONF_POINTER(PW_TYPE_IPV4PREFIX, &cl_ipaddr), NULL }, { "ipv6addr", FR_CONF_POINTER(PW_TYPE_IPV6PREFIX, &cl_ipaddr), NULL }, { "netmask", FR_CONF_POINTER(PW_TYPE_INTEGER, &cl_prefix), NULL }, diff --git a/src/main/conffile.c b/src/main/conffile.c index 6e96800463a3..e19495645918 100644 --- a/src/main/conffile.c +++ b/src/main/conffile.c @@ -903,6 +903,53 @@ static char const *cf_expand_variables(char const *cf, int *lineno, static char const *parse_spaces = " "; +/** Validation function for ipaddr conffile types + * + */ +static inline int fr_item_validate_ipaddr(CONF_SECTION *cs, char const *name, PW_TYPE type, char const *value, + fr_ipaddr_t *ipaddr) +{ + char ipbuf[128]; + + if (strcmp(value, "*") == 0) { + cf_log_info(cs, "%.*s\t%s = *", cs->depth, parse_spaces, name); + } else if (strspn(value, ".0123456789abdefABCDEF:%[]/") == strlen(value)) { + cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, name, value); + } else { + cf_log_info(cs, "%.*s\t%s = %s IPv%s address [%s]", cs->depth, parse_spaces, name, value, + (ipaddr->af == AF_INET ? "4" : " 6"), ip_ntoh(ipaddr, ipbuf, sizeof(ipbuf))); + } + + switch (type) { + case PW_TYPE_IPADDR: + case PW_TYPE_IPV6ADDR: + case PW_TYPE_COMBO_IP: + switch (ipaddr->af) { + case AF_INET: + if (ipaddr->prefix != 32) { + ERROR("Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted for non-prefix types", + ipaddr->prefix); + + return -1; + } + break; + + case AF_INET6: + if (ipaddr->prefix != 128) { + ERROR("Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted for non-prefix types", + ipaddr->prefix); + + return -1; + } + break; + + default: + return -1; + } + default: + return 0; + } +} /* * Parses an item (not a CONF_ITEM) into the specified format, @@ -919,6 +966,7 @@ int cf_item_parse(CONF_SECTION *cs, char const *name, int type, void *data, char char **q; char const *value; CONF_PAIR const *cp = NULL; + fr_ipaddr_t *ipaddr; char buffer[8192]; if (!cs) return -1; @@ -1138,66 +1186,35 @@ int cf_item_parse(CONF_SECTION *cs, char const *name, int type, void *data, char case PW_TYPE_IPADDR: case PW_TYPE_IPV4PREFIX: - { - fr_ipaddr_t *ipaddr = data; - char ipbuf[128]; + ipaddr = data; if (fr_pton4(ipaddr, value, 0, true, false) < 0) { ERROR("%s", fr_strerror()); return -1; } - - /* - * Debug format depends on format of input string - */ - if (strcmp(value, "*") == 0) { - cf_log_info(cs, "%.*s\t%s = *", cs->depth, parse_spaces, name); - } else if ((strspn(value, "0123456789./") == strlen(value)) || - (strspn(value, "0123456789xabcdefABCDEF/") == strlen(value))) { - cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, name, value); - } else { - cf_log_info(cs, "%.*s\t%s = %s IP address [%s]", - cs->depth, parse_spaces, name, value, ip_ntoh(ipaddr, ipbuf, sizeof(ipbuf))); - } - - if ((type == PW_TYPE_IPADDR) && (ipaddr->prefix != 32)) { - ERROR("Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted for non-prefix types", - ipaddr->prefix); - return -1; - } - } + if (fr_item_validate_ipaddr(cs, name, type, value, ipaddr) < 0) return -1; break; case PW_TYPE_IPV6ADDR: case PW_TYPE_IPV6PREFIX: - { - fr_ipaddr_t *ipaddr = data; - char ipbuf[128]; + ipaddr = data; if (fr_pton6(ipaddr, value, 0, true, false) < 0) { ERROR("%s", fr_strerror()); return -1; } + if (fr_item_validate_ipaddr(cs, name, type, value, ipaddr) < 0) return -1; + break; - /* - * Debug format depends on format of input string - */ - if (strcmp(value, "*") == 0) { - cf_log_info(cs, "%.*s\t%s = *", cs->depth, parse_spaces, name); - } else if (strspn(value, "0123456789abdefABCDEF:%[]/") == strlen(value)) { - cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, name, value); - } else { - cf_log_info(cs, "%.*s\t%s = %s IPv6 address [%s]", cs->depth, parse_spaces, name, value, - ip_ntoh(ipaddr, ipbuf, sizeof(ipbuf))); - } + case PW_TYPE_COMBO_IP: + case PW_TYPE_COMBO_IPPREFIX: + ipaddr = data; - if ((type == PW_TYPE_IPV6ADDR) && (ipaddr->prefix != 128)) { - ERROR("Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted " - "for non-prefix types", ipaddr->prefix); + if (fr_pton(ipaddr, value, 0, true) < 0) { + ERROR("%s", fr_strerror()); return -1; } - } - + if (fr_item_validate_ipaddr(cs, name, type, value, ipaddr) < 0) return -1; break; case PW_TYPE_TIMEVAL: {