]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Allow an af to be specified for fr_pton
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 20 Jul 2015 18:03:44 +0000 (14:03 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 20 Jul 2015 18:24:08 +0000 (14:24 -0400)
This controls which record we use if the address doesn't look like a v4 or v6 address.

Additionally inet_pton doesn't like addresses being wrapped in [], so strip them off in fr_pton_port.

src/include/libradius.h
src/lib/misc.c
src/main/client.c
src/main/conffile.c
src/main/mainconfig.c

index a42426796fc28e04602e70c9b0789617a2e317cd..a6d20f782fc995d3f76831f96618b0fcd3c6016a 100644 (file)
@@ -706,8 +706,9 @@ char const  *fr_inet_ntop(int af, void const *src);
 char const     *ip_ntoa(char *, uint32_t);
 int            fr_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback);
 int            fr_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback);
-int            fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve);
-int            fr_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, bool resolve);
+int            fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, int af, bool resolve);
+int            fr_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, int af,
+                            bool resolve);
 int            fr_ntop(char *out, size_t outlen, fr_ipaddr_t *addr);
 char           *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid);
 uint8_t                *ifid_aton(char const *ifid_str, uint8_t *ifid);
index c80c36b7712468723dd223b689ffa905179299ac..a4b92a4416878209094f1a475ecec0e54a23170c 100644 (file)
@@ -397,25 +397,29 @@ int fr_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, b
 
 /** Simple wrapper to decide whether an IP value is v4 or v6 and call the appropriate parser.
  *
- * @param out Where to write the ip address value.
- * @param value to parse.
- * @param inlen Length of value, if value is \0 terminated inlen may be -1.
- * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
- * @return 0 if ip address was parsed successfully, else -1 on error.
+ * @param[out] out Where to write the ip address value.
+ * @param[in] value to parse.
+ * @param[in] inlen Length of value, if value is \0 terminated inlen may be -1.
+ * @param[in] resolve If true and value doesn't look like an IP address, try and resolve value as a
+ *     hostname.
+ * @param[in] af If the address type is not obvious from the format, and resolve is true, the DNS
+ *     record (A or AAAA) we require.  Also controls which parser we pass the address to if
+ *     we have no idea what it is.
+ * @return
+ *     - 0 if ip address was parsed successfully.
+ *     - -1 on failure.
  */
-int fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve)
+int fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, int af, bool resolve)
 {
        size_t len, i;
 
        len = (inlen >= 0) ? (size_t)inlen : strlen(value);
        for (i = 0; i < len; i++) switch (value[i]) {
        /*
-        *      Chars illegal in domain names and IPv4 addresses.
+        *      ':' is illegal in domain names and IPv4 addresses.
         *      Must be v6 and cannot be a domain.
         */
        case ':':
-       case '[':
-       case ']':
                return fr_pton6(out, value, inlen, false, false);
 
        /*
@@ -435,7 +439,20 @@ int fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve)
                                fr_strerror_printf("Not IPv4/6 address, and asked not to resolve");
                                return -1;
                        }
-                       return fr_pton4(out, value, inlen, true, true);
+                       switch (af) {
+                       case AF_UNSPEC:
+                               return fr_pton4(out, value, inlen, resolve, true);
+
+                       case AF_INET:
+                               return fr_pton4(out, value, inlen, resolve, false);
+
+                       case AF_INET6:
+                               return fr_pton6(out, value, inlen, resolve, false);
+
+                       default:
+                               fr_strerror_printf("Invalid address family %i", af);
+                               return -1;
+                       }
                }
                break;
        }
@@ -453,10 +470,13 @@ int fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve)
  * @param[out] port_out Where to write the port (0 if no port found).
  * @param[in] value to parse.
  * @param[in] inlen Length of value, if value is \0 terminated inlen may be -1.
+ * @param[in] af If the address type is not obvious from the format, and resolve is true, the DNS
+ *     record (A or AAAA) we require.  Also controls which parser we pass the address to if
+ *     we have no idea what it is.
  * @param[in] resolve If true and value doesn't look like an IP address, try and resolve value as a
  *     hostname.
  */
-int fr_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, bool resolve)
+int fr_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, int af, bool resolve)
 {
        char const      *p = value, *q;
        char            *end;
@@ -474,7 +494,10 @@ int fr_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_
                        return -1;
                }
 
-               if (fr_pton6(out, p, (q - p) + 1, false, false) < 0) return -1;
+               /*
+                *      inet_pton doesn't like the address being wrapped in []
+                */
+               if (fr_pton6(out, p + 1, (q - p) - 1, false, false) < 0) return -1;
 
                if (q[1] == ':') {
                        q++;
@@ -485,18 +508,15 @@ int fr_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_
        }
 
        /*
-        *      IPv4 or host, with no port
+        *      Host, IPv4 or IPv6 with no port
         */
        q = memchr(p, ':', len);
-       if (!q) {
-               if (fr_pton(out, p, len, resolve) < 0) return -1;
-               return 0;
-       }
+       if (!q || !memchr(p, '.', len)) return fr_pton(out, p, len, af, resolve);
 
        /*
         *      IPv4 or host, with port
         */
-       if (fr_pton(out, p, (q - p), true) < 0) return -1;
+       if (fr_pton(out, p, (q - p), af, resolve) < 0) return -1;
 do_port:
        /*
         *      Valid ports are a maximum of 5 digits, so if the
index 408ea74be19c1b84d8f6eb7d4de6c13806a58364..8f42ffc143e29c994788aace98a2160daf78aff4 100644 (file)
@@ -1156,7 +1156,7 @@ RADCLIENT *client_afrom_query(TALLOC_CTX *ctx, char const *identifier, char cons
 
        c = talloc_zero(ctx, RADCLIENT);
 
-       if (fr_pton(&c->ipaddr, identifier, -1, true) < 0) {
+       if (fr_pton(&c->ipaddr, identifier, -1, AF_UNSPEC, true) < 0) {
                ERROR("%s", fr_strerror());
                talloc_free(c);
 
index e15416433b2ae32f09ca3eff140690145d9fd10f..904b65ed2ff2adfffecb0821c2c4bf17d0f5b06c 100644 (file)
@@ -1668,7 +1668,7 @@ int cf_item_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *d
        case PW_TYPE_COMBO_IP_PREFIX:
                ipaddr = data;
 
-               if (fr_pton(ipaddr, value, -1, true) < 0) {
+               if (fr_pton(ipaddr, value, -1, AF_UNSPEC, true) < 0) {
                        ERROR("%s", fr_strerror());
                        return -1;
                }
index ca2a811c116c75b770fefa46c24f87385acacd9f..a082d6c0c0e28cf983bada9ba354bad956a85d76 100644 (file)
@@ -423,7 +423,7 @@ static ssize_t xlat_getclient(UNUSED void *instance, REQUEST *request, char cons
        }
 
        strlcpy(buffer, p, (q + 1) - p);
-       if (fr_pton(&ip, buffer, -1, false) < 0) {
+       if (fr_pton(&ip, buffer, -1, AF_UNSPEC, false) < 0) {
                REDEBUG("\"%s\" is not a valid IPv4 or IPv6 address", buffer);
                goto error;
        }