]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: pattern/ip: offload ip conversion logic to helper functions
authorAurelien DARRAGON <adarragon@haproxy.com>
Tue, 5 Sep 2023 12:58:53 +0000 (14:58 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 21 Sep 2023 07:50:55 +0000 (09:50 +0200)
Now that v4tov6() and v6tov4() were reworked to match behavior from
pat_match_ip() function in ("MINOR: tools/ip: v4tov6() and v6tov4()
rework"), we can remove code duplication in pat_match_ip() by directly
using those dedicated functions where relevant.

src/pattern.c

index b393112d3060ab8fb4e4910e4b2f37d26947c720..0a71237f3b6aa12a791af2504f11baa4d6369521 100644 (file)
@@ -966,7 +966,7 @@ struct pattern *pat_match_len(struct sample *smp, struct pattern_expr *expr, int
 
 struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int fill)
 {
-       unsigned int v4; /* in network byte order */
+       struct in_addr v4; /* in network byte order */
        struct in6_addr tmp6;
        struct in_addr *s;
        struct ebmb_node *node;
@@ -1000,12 +1000,9 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
                }
 
                /* The IPv4 sample don't match the IPv4 tree. Convert the IPv4
-                * sample address to IPv6 with the mapping method using the ::ffff:
-                * prefix, and try to lookup in the IPv6 tree.
+                * sample address to IPv6 and try to lookup in the IPv6 tree.
                 */
-               memset(&tmp6, 0, 10);
-               write_u16(&tmp6.s6_addr[10], htons(0xffff));
-               write_u32(&tmp6.s6_addr[12], smp->data.u.ipv4.s_addr);
+               v4tov6(&tmp6, &smp->data.u.ipv4);
                node = ebmb_lookup_longest(&expr->pattern_tree_2, &tmp6);
                while (node) {
                        elt = ebmb_entry(node, struct pattern_tree, node);
@@ -1048,22 +1045,8 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
                        return &static_pattern;
                }
 
-               /* Try to convert 6 to 4 when the start of the ipv6 address match the
-                * following forms :
-                *   - ::ffff:ip:v4 (ipv4 mapped)
-                *   - ::0000:ip:v4 (old ipv4 mapped)
-                *   - 2002:ip:v4:: (6to4)
-                */
-               if ((read_u64(&smp->data.u.ipv6.s6_addr[0]) == 0 &&
-                    (read_u32(&smp->data.u.ipv6.s6_addr[8]) == 0 ||
-                     read_u32(&smp->data.u.ipv6.s6_addr[8]) == htonl(0xFFFF))) ||
-                   read_u16(&smp->data.u.ipv6.s6_addr[0]) == htons(0x2002)) {
-                       if (read_u32(&smp->data.u.ipv6.s6_addr[0]) == 0)
-                               v4 = read_u32(&smp->data.u.ipv6.s6_addr[12]);
-                       else
-                               v4 = htonl((ntohs(read_u16(&smp->data.u.ipv6.s6_addr[2])) << 16) +
-                                          ntohs(read_u16(&smp->data.u.ipv6.s6_addr[4])));
-
+               /* Try to convert 6 to 4 */
+               if (v6tov4(&v4, &smp->data.u.ipv6)) {
                        /* Lookup an IPv4 address in the expression's pattern tree using the longest
                         * match method.
                         */
@@ -1097,25 +1080,11 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
 
                /* The input sample is IPv4, use it as is. */
                if (smp->data.type == SMP_T_IPV4) {
-                       v4 = smp->data.u.ipv4.s_addr;
+                       v4.s_addr = smp->data.u.ipv4.s_addr;
                }
                else if (smp->data.type == SMP_T_IPV6) {
-                       /* v4 match on a V6 sample. We want to check at least for
-                        * the following forms :
-                        *   - ::ffff:ip:v4 (ipv4 mapped)
-                        *   - ::0000:ip:v4 (old ipv4 mapped)
-                        *   - 2002:ip:v4:: (6to4)
-                        */
-                       if (read_u64(&smp->data.u.ipv6.s6_addr[0]) == 0 &&
-                           (read_u32(&smp->data.u.ipv6.s6_addr[8]) == 0 ||
-                            read_u32(&smp->data.u.ipv6.s6_addr[8]) == htonl(0xFFFF))) {
-                               v4 = read_u32(&smp->data.u.ipv6.s6_addr[12]);
-                       }
-                       else if (read_u16(&smp->data.u.ipv6.s6_addr[0]) == htons(0x2002)) {
-                               v4 = htonl((ntohs(read_u16(&smp->data.u.ipv6.s6_addr[2])) << 16) +
-                                          ntohs(read_u16(&smp->data.u.ipv6.s6_addr[4])));
-                       }
-                       else
+                       /* v4 match on a V6 sample. Try to convert v6 form to v4 address */
+                       if (!v6tov4(&v4, &smp->data.u.ipv6))
                                continue;
                } else {
                  /* impossible */
@@ -1123,7 +1092,7 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
                }
 
                /* Check if the input sample match the current pattern. */
-               if (((v4 ^ pattern->val.ipv4.addr.s_addr) & pattern->val.ipv4.mask.s_addr) == 0)
+               if (((v4.s_addr ^ pattern->val.ipv4.addr.s_addr) & pattern->val.ipv4.mask.s_addr) == 0)
                        return pattern;
        }
        return NULL;