ipv6: use TOS marks from sockets for routing decision
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Sat, 11 Jun 2016 18:08:19 +0000 (20:08 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 11 Jun 2016 22:33:26 +0000 (15:33 -0700)
In IPv6 the ToS values are part of the flowlabel in flowi6 and get
extracted during fib rule lookup, but we forgot to correctly initialize
the flowlabel before the routing lookup.

Reported-by: <liam.mcbirnie@boeing.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/icmp.c
net/ipv6/ping.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/udp.c
net/l2tp/l2tp_ip6.c

index 4527285fcaa2c2c8134c089b88e0cfeeeddad292..40454bfb534ed09692bbca8a69c0f65539cbf383 100644 (file)
@@ -502,12 +502,14 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        else if (!fl6.flowi6_oif)
                fl6.flowi6_oif = np->ucast_oif;
 
+       ipc6.tclass = np->tclass;
+       fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
+
        dst = icmpv6_route_lookup(net, skb, sk, &fl6);
        if (IS_ERR(dst))
                goto out;
 
        ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
-       ipc6.tclass = np->tclass;
        ipc6.dontfrag = np->dontfrag;
        ipc6.opt = NULL;
 
index 3ee3e444a66befb01e1a2f124417264361d4a8f6..fed40d1ec29b1fc331ad04b5a7173b183a116279 100644 (file)
@@ -116,6 +116,9 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        else if (!fl6.flowi6_oif)
                fl6.flowi6_oif = np->ucast_oif;
 
+       ipc6.tclass = np->tclass;
+       fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
+
        dst = ip6_sk_dst_lookup_flow(sk, &fl6,  daddr);
        if (IS_ERR(dst))
                return PTR_ERR(dst);
@@ -140,7 +143,6 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        pfh.family = AF_INET6;
 
        ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
-       ipc6.tclass = np->tclass;
        ipc6.dontfrag = np->dontfrag;
        ipc6.opt = NULL;
 
index 896350df642361650234748965414df43adf0958..590dd1f7746fca063525098553f085fff86bf4b4 100644 (file)
@@ -878,6 +878,11 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        if (inet->hdrincl)
                fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH;
 
+       if (ipc6.tclass < 0)
+               ipc6.tclass = np->tclass;
+
+       fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
+
        dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
@@ -886,9 +891,6 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        if (ipc6.hlimit < 0)
                ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
 
-       if (ipc6.tclass < 0)
-               ipc6.tclass = np->tclass;
-
        if (ipc6.dontfrag < 0)
                ipc6.dontfrag = np->dontfrag;
 
index 969913da494fdf1d80ce674c3b6c421fdab18d3d..c6ae6f9b5fe31cbc6581837dd5371b3df1207ccb 100644 (file)
@@ -3306,6 +3306,8 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
 
        err = -EINVAL;
        memset(&fl6, 0, sizeof(fl6));
+       rtm = nlmsg_data(nlh);
+       fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
 
        if (tb[RTA_SRC]) {
                if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
index f421c9f23c5bef7bf58937635474713cf4722516..4bb5c13777f1baf55dcf9af5c58ddd64a27c8167 100644 (file)
@@ -1246,6 +1246,11 @@ do_udp_sendmsg:
 
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
+       if (ipc6.tclass < 0)
+               ipc6.tclass = np->tclass;
+
+       fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
+
        dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
@@ -1256,9 +1261,6 @@ do_udp_sendmsg:
        if (ipc6.hlimit < 0)
                ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
 
-       if (ipc6.tclass < 0)
-               ipc6.tclass = np->tclass;
-
        if (msg->msg_flags&MSG_CONFIRM)
                goto do_confirm;
 back_from_confirm:
index 6c54e03fe9c1751217e246f31d6ca1f322762539..ea2ae6664cc8d643319016ea7a234dc034ec590e 100644 (file)
@@ -611,6 +611,11 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
+       if (ipc6.tclass < 0)
+               ipc6.tclass = np->tclass;
+
+       fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
+
        dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
@@ -620,9 +625,6 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        if (ipc6.hlimit < 0)
                ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
 
-       if (ipc6.tclass < 0)
-               ipc6.tclass = np->tclass;
-
        if (ipc6.dontfrag < 0)
                ipc6.dontfrag = np->dontfrag;