diff options
author | Francesco Fusco <ffusco@redhat.com> | 2013-09-24 09:43:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-09-28 18:21:52 -0400 |
commit | aa6615814533c634190019ee3a5b10490026d545 (patch) | |
tree | 08543d020bd7e2500046143440d58cd031f9754c /net | |
parent | f02db315b8d888570cb0d4496cfbb7e4acb047cb (diff) |
ipv4: processing ancillary IP_TOS or IP_TTL
If IP_TOS or IP_TTL are specified as ancillary data, then sendmsg() sends out
packets with the specified TTL or TOS overriding the socket values specified
with the traditional setsockopt().
The struct inet_cork stores the values of TOS, TTL and priority that are
passed through the struct ipcm_cookie. If there are user-specified TOS
(tos != -1) or TTL (ttl != 0) in the struct ipcm_cookie, these values are
used to override the per-socket values. In case of TOS also the priority
is changed accordingly.
Two helper functions get_rttos and get_rtconn_flags are defined to take
into account the presence of a user specified TOS value when computing
RT_TOS and RT_CONN_FLAGS.
Signed-off-by: Francesco Fusco <ffusco@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/icmp.c | 5 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 13 | ||||
-rw-r--r-- | net/ipv4/ping.c | 4 | ||||
-rw-r--r-- | net/ipv4/raw.c | 4 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 |
5 files changed, 24 insertions, 6 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 5f7d11a45871..5c0e8bc6e5ba 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -353,6 +353,9 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
353 | saddr = fib_compute_spec_dst(skb); | 353 | saddr = fib_compute_spec_dst(skb); |
354 | ipc.opt = NULL; | 354 | ipc.opt = NULL; |
355 | ipc.tx_flags = 0; | 355 | ipc.tx_flags = 0; |
356 | ipc.ttl = 0; | ||
357 | ipc.tos = -1; | ||
358 | |||
356 | if (icmp_param->replyopts.opt.opt.optlen) { | 359 | if (icmp_param->replyopts.opt.opt.optlen) { |
357 | ipc.opt = &icmp_param->replyopts.opt; | 360 | ipc.opt = &icmp_param->replyopts.opt; |
358 | if (ipc.opt->opt.srr) | 361 | if (ipc.opt->opt.srr) |
@@ -608,6 +611,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
608 | ipc.addr = iph->saddr; | 611 | ipc.addr = iph->saddr; |
609 | ipc.opt = &icmp_param->replyopts.opt; | 612 | ipc.opt = &icmp_param->replyopts.opt; |
610 | ipc.tx_flags = 0; | 613 | ipc.tx_flags = 0; |
614 | ipc.ttl = 0; | ||
615 | ipc.tos = -1; | ||
611 | 616 | ||
612 | rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, | 617 | rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, |
613 | type, code, icmp_param); | 618 | type, code, icmp_param); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index a04d872c54f9..7d8357bb2ba6 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -1060,6 +1060,9 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, | |||
1060 | rt->dst.dev->mtu : dst_mtu(&rt->dst); | 1060 | rt->dst.dev->mtu : dst_mtu(&rt->dst); |
1061 | cork->dst = &rt->dst; | 1061 | cork->dst = &rt->dst; |
1062 | cork->length = 0; | 1062 | cork->length = 0; |
1063 | cork->ttl = ipc->ttl; | ||
1064 | cork->tos = ipc->tos; | ||
1065 | cork->priority = ipc->priority; | ||
1063 | cork->tx_flags = ipc->tx_flags; | 1066 | cork->tx_flags = ipc->tx_flags; |
1064 | 1067 | ||
1065 | return 0; | 1068 | return 0; |
@@ -1311,7 +1314,9 @@ struct sk_buff *__ip_make_skb(struct sock *sk, | |||
1311 | if (cork->flags & IPCORK_OPT) | 1314 | if (cork->flags & IPCORK_OPT) |
1312 | opt = cork->opt; | 1315 | opt = cork->opt; |
1313 | 1316 | ||
1314 | if (rt->rt_type == RTN_MULTICAST) | 1317 | if (cork->ttl != 0) |
1318 | ttl = cork->ttl; | ||
1319 | else if (rt->rt_type == RTN_MULTICAST) | ||
1315 | ttl = inet->mc_ttl; | 1320 | ttl = inet->mc_ttl; |
1316 | else | 1321 | else |
1317 | ttl = ip_select_ttl(inet, &rt->dst); | 1322 | ttl = ip_select_ttl(inet, &rt->dst); |
@@ -1319,7 +1324,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, | |||
1319 | iph = ip_hdr(skb); | 1324 | iph = ip_hdr(skb); |
1320 | iph->version = 4; | 1325 | iph->version = 4; |
1321 | iph->ihl = 5; | 1326 | iph->ihl = 5; |
1322 | iph->tos = inet->tos; | 1327 | iph->tos = (cork->tos != -1) ? cork->tos : inet->tos; |
1323 | iph->frag_off = df; | 1328 | iph->frag_off = df; |
1324 | iph->ttl = ttl; | 1329 | iph->ttl = ttl; |
1325 | iph->protocol = sk->sk_protocol; | 1330 | iph->protocol = sk->sk_protocol; |
@@ -1331,7 +1336,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, | |||
1331 | ip_options_build(skb, opt, cork->addr, rt, 0); | 1336 | ip_options_build(skb, opt, cork->addr, rt, 0); |
1332 | } | 1337 | } |
1333 | 1338 | ||
1334 | skb->priority = sk->sk_priority; | 1339 | skb->priority = (cork->tos != -1) ? cork->priority: sk->sk_priority; |
1335 | skb->mark = sk->sk_mark; | 1340 | skb->mark = sk->sk_mark; |
1336 | /* | 1341 | /* |
1337 | * Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec | 1342 | * Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec |
@@ -1481,6 +1486,8 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, | |||
1481 | ipc.addr = daddr; | 1486 | ipc.addr = daddr; |
1482 | ipc.opt = NULL; | 1487 | ipc.opt = NULL; |
1483 | ipc.tx_flags = 0; | 1488 | ipc.tx_flags = 0; |
1489 | ipc.ttl = 0; | ||
1490 | ipc.tos = -1; | ||
1484 | 1491 | ||
1485 | if (replyopts.opt.opt.optlen) { | 1492 | if (replyopts.opt.opt.optlen) { |
1486 | ipc.opt = &replyopts.opt; | 1493 | ipc.opt = &replyopts.opt; |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index d7d9882d4cae..706d108e128c 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -713,6 +713,8 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
713 | ipc.opt = NULL; | 713 | ipc.opt = NULL; |
714 | ipc.oif = sk->sk_bound_dev_if; | 714 | ipc.oif = sk->sk_bound_dev_if; |
715 | ipc.tx_flags = 0; | 715 | ipc.tx_flags = 0; |
716 | ipc.ttl = 0; | ||
717 | ipc.tos = -1; | ||
716 | 718 | ||
717 | sock_tx_timestamp(sk, &ipc.tx_flags); | 719 | sock_tx_timestamp(sk, &ipc.tx_flags); |
718 | 720 | ||
@@ -744,7 +746,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
744 | return -EINVAL; | 746 | return -EINVAL; |
745 | faddr = ipc.opt->opt.faddr; | 747 | faddr = ipc.opt->opt.faddr; |
746 | } | 748 | } |
747 | tos = RT_TOS(inet->tos); | 749 | tos = get_rttos(&ipc, inet); |
748 | if (sock_flag(sk, SOCK_LOCALROUTE) || | 750 | if (sock_flag(sk, SOCK_LOCALROUTE) || |
749 | (msg->msg_flags & MSG_DONTROUTE) || | 751 | (msg->msg_flags & MSG_DONTROUTE) || |
750 | (ipc.opt && ipc.opt->opt.is_strictroute)) { | 752 | (ipc.opt && ipc.opt->opt.is_strictroute)) { |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index bfec521c717f..a3fe534c968e 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -517,6 +517,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
517 | ipc.addr = inet->inet_saddr; | 517 | ipc.addr = inet->inet_saddr; |
518 | ipc.opt = NULL; | 518 | ipc.opt = NULL; |
519 | ipc.tx_flags = 0; | 519 | ipc.tx_flags = 0; |
520 | ipc.ttl = 0; | ||
521 | ipc.tos = -1; | ||
520 | ipc.oif = sk->sk_bound_dev_if; | 522 | ipc.oif = sk->sk_bound_dev_if; |
521 | 523 | ||
522 | if (msg->msg_controllen) { | 524 | if (msg->msg_controllen) { |
@@ -556,7 +558,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
556 | daddr = ipc.opt->opt.faddr; | 558 | daddr = ipc.opt->opt.faddr; |
557 | } | 559 | } |
558 | } | 560 | } |
559 | tos = RT_CONN_FLAGS(sk); | 561 | tos = get_rtconn_flags(&ipc, sk); |
560 | if (msg->msg_flags & MSG_DONTROUTE) | 562 | if (msg->msg_flags & MSG_DONTROUTE) |
561 | tos |= RTO_ONLINK; | 563 | tos |= RTO_ONLINK; |
562 | 564 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 74d2c95db57f..22462d947750 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -855,6 +855,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
855 | 855 | ||
856 | ipc.opt = NULL; | 856 | ipc.opt = NULL; |
857 | ipc.tx_flags = 0; | 857 | ipc.tx_flags = 0; |
858 | ipc.ttl = 0; | ||
859 | ipc.tos = -1; | ||
858 | 860 | ||
859 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; | 861 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
860 | 862 | ||
@@ -938,7 +940,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
938 | faddr = ipc.opt->opt.faddr; | 940 | faddr = ipc.opt->opt.faddr; |
939 | connected = 0; | 941 | connected = 0; |
940 | } | 942 | } |
941 | tos = RT_TOS(inet->tos); | 943 | tos = get_rttos(&ipc, inet); |
942 | if (sock_flag(sk, SOCK_LOCALROUTE) || | 944 | if (sock_flag(sk, SOCK_LOCALROUTE) || |
943 | (msg->msg_flags & MSG_DONTROUTE) || | 945 | (msg->msg_flags & MSG_DONTROUTE) || |
944 | (ipc.opt && ipc.opt->opt.is_strictroute)) { | 946 | (ipc.opt && ipc.opt->opt.is_strictroute)) { |