]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http: add IPv6 support for "set-tos"
authorLukas Tribus <luky-37@hotmail.com>
Sun, 23 Jun 2013 15:37:13 +0000 (17:37 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 23 Jun 2013 16:01:38 +0000 (18:01 +0200)
As per RFC3260 #4 and BCP37 #4.2 and #5.2, the IPv6 counterpart of TOS
is "traffic class".

Add support for IPv6 traffic class in "set-tos" by moving the "set-tos"
related code to the new inline function inet_set_tos(), handling IPv4
(IP_TOS), IPv6 (IPV6_TCLASS) and IPv4-mapped sockets (IP_TOS, like
::ffff:127.0.0.1).

Also define - if missing - the IN6_IS_ADDR_V4MAPPED() macro in
include/common/compat.h for compatibility.

include/common/compat.h
src/proto_http.c

index a0764b103a6c2d93e6471a323668c5a4ae37ed56..48ea1f710be2d67950a783e0cf7dadacda3ccfe8 100644 (file)
 #endif
 #endif
 
+/* If IPv6 is supported, define IN6_IS_ADDR_V4MAPPED() if missing. */
+#if defined(IPV6_TCLASS) && !defined(IN6_IS_ADDR_V4MAPPED)
+#define IN6_IS_ADDR_V4MAPPED(a) \
+((((const uint32_t *) (a))[0] == 0) \
+&& (((const uint32_t *) (a))[1] == 0) \
+&& (((const uint32_t *) (a))[2] == htonl (0xffff)))
+#endif
+
 #if defined(__dietlibc__)
 #include <strings.h>
 #endif
index d21bd8a4e1135aff48d6b03dba0d9a06ab9ffec6..8c336e6bb63e358c29314f104910c5bdc7d9b78c 100644 (file)
@@ -3158,6 +3158,26 @@ int http_handle_stats(struct session *s, struct channel *req)
        return 1;
 }
 
+/* Sets the TOS header in IPv4 and the traffic class header in IPv6 packets
+ * (as per RFC3260 #4 and BCP37 #4.2 and #5.2).
+ */
+static inline void inet_set_tos(int fd, struct sockaddr_storage from, int tos)
+{
+#ifdef IP_TOS
+       if (from.ss_family == AF_INET)
+               setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+#endif
+#ifdef IPV6_TCLASS
+       if (from.ss_family == AF_INET6) {
+               if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr))
+                       /* v4-mapped addresses need IP_TOS */
+                       setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+               else
+                       setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos));
+       }
+#endif
+}
+
 /* Executes the http-request rules <rules> for session <s>, proxy <px> and
  * transaction <txn>. Returns the first rule that prevents further processing
  * of the request (auth, deny, ...) or NULL if it executed all rules or stopped
@@ -3212,10 +3232,7 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session
                        break;
 
                case HTTP_REQ_ACT_SET_TOS:
-#ifdef IP_TOS
-                       if (s->req->prod->conn->addr.from.ss_family == AF_INET)
-                               setsockopt(s->req->prod->conn->t.sock.fd, IPPROTO_IP, IP_TOS, &rule->arg.tos, sizeof(rule->arg.tos));
-#endif
+                       inet_set_tos(s->req->prod->conn->t.sock.fd, s->req->prod->conn->addr.from, rule->arg.tos);
                        break;
 
                case HTTP_REQ_ACT_SET_MARK:
@@ -3298,10 +3315,7 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session
                        break;
 
                case HTTP_RES_ACT_SET_TOS:
-#ifdef IP_TOS
-                       if (s->req->prod->conn->addr.from.ss_family == AF_INET)
-                               setsockopt(s->req->prod->conn->t.sock.fd, IPPROTO_IP, IP_TOS, &rule->arg.tos, sizeof(rule->arg.tos));
-#endif
+                       inet_set_tos(s->req->prod->conn->t.sock.fd, s->req->prod->conn->addr.from, rule->arg.tos);
                        break;
 
                case HTTP_RES_ACT_SET_MARK: