aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorFrancesco Fusco <ffusco@redhat.com>2013-09-24 09:43:09 -0400
committerDavid S. Miller <davem@davemloft.net>2013-09-28 18:21:52 -0400
commitaa6615814533c634190019ee3a5b10490026d545 (patch)
tree08543d020bd7e2500046143440d58cd031f9754c /net
parentf02db315b8d888570cb0d4496cfbb7e4acb047cb (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.c5
-rw-r--r--net/ipv4/ip_output.c13
-rw-r--r--net/ipv4/ping.c4
-rw-r--r--net/ipv4/raw.c4
-rw-r--r--net/ipv4/udp.c4
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)) {