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 4527285..40454bf 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 3ee3e44..fed40d1 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 896350d..590dd1f 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 969913d..c6ae6f9 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 f421c9f..4bb5c13 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 6c54e03..ea2ae66 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;