Skip to content

Commit aa66158

Browse files
Francesco Fuscodavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f02db31 commit aa66158

File tree

8 files changed

+39
-6
lines changed

8 files changed

+39
-6
lines changed

include/net/inet_sock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ struct inet_cork {
103103
int length; /* Total length of all frames */
104104
struct dst_entry *dst;
105105
u8 tx_flags;
106+
__u8 ttl;
107+
__s16 tos;
108+
char priority;
106109
};
107110

108111
struct inet_cork_full {

include/net/ip.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/skbuff.h>
2929

3030
#include <net/inet_sock.h>
31+
#include <net/route.h>
3132
#include <net/snmp.h>
3233
#include <net/flow.h>
3334

@@ -140,6 +141,16 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
140141
return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
141142
}
142143

144+
static inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet)
145+
{
146+
return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos);
147+
}
148+
149+
static inline __u8 get_rtconn_flags(struct ipcm_cookie* ipc, struct sock* sk)
150+
{
151+
return (ipc->tos != -1) ? RT_CONN_FLAGS_TOS(sk, ipc->tos) : RT_CONN_FLAGS(sk);
152+
}
153+
143154
/* datagram.c */
144155
int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
145156

include/net/route.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define RTO_ONLINK 0x01
4040

4141
#define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE))
42+
#define RT_CONN_FLAGS_TOS(sk,tos) (RT_TOS(tos) | sock_flag(sk, SOCK_LOCALROUTE))
4243

4344
struct fib_nh;
4445
struct fib_info;

net/ipv4/icmp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
353353
saddr = fib_compute_spec_dst(skb);
354354
ipc.opt = NULL;
355355
ipc.tx_flags = 0;
356+
ipc.ttl = 0;
357+
ipc.tos = -1;
358+
356359
if (icmp_param->replyopts.opt.opt.optlen) {
357360
ipc.opt = &icmp_param->replyopts.opt;
358361
if (ipc.opt->opt.srr)
@@ -608,6 +611,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
608611
ipc.addr = iph->saddr;
609612
ipc.opt = &icmp_param->replyopts.opt;
610613
ipc.tx_flags = 0;
614+
ipc.ttl = 0;
615+
ipc.tos = -1;
611616

612617
rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
613618
type, code, icmp_param);

net/ipv4/ip_output.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,9 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
10601060
rt->dst.dev->mtu : dst_mtu(&rt->dst);
10611061
cork->dst = &rt->dst;
10621062
cork->length = 0;
1063+
cork->ttl = ipc->ttl;
1064+
cork->tos = ipc->tos;
1065+
cork->priority = ipc->priority;
10631066
cork->tx_flags = ipc->tx_flags;
10641067

10651068
return 0;
@@ -1311,15 +1314,17 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
13111314
if (cork->flags & IPCORK_OPT)
13121315
opt = cork->opt;
13131316

1314-
if (rt->rt_type == RTN_MULTICAST)
1317+
if (cork->ttl != 0)
1318+
ttl = cork->ttl;
1319+
else if (rt->rt_type == RTN_MULTICAST)
13151320
ttl = inet->mc_ttl;
13161321
else
13171322
ttl = ip_select_ttl(inet, &rt->dst);
13181323

13191324
iph = ip_hdr(skb);
13201325
iph->version = 4;
13211326
iph->ihl = 5;
1322-
iph->tos = inet->tos;
1327+
iph->tos = (cork->tos != -1) ? cork->tos : inet->tos;
13231328
iph->frag_off = df;
13241329
iph->ttl = ttl;
13251330
iph->protocol = sk->sk_protocol;
@@ -1331,7 +1336,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
13311336
ip_options_build(skb, opt, cork->addr, rt, 0);
13321337
}
13331338

1334-
skb->priority = sk->sk_priority;
1339+
skb->priority = (cork->tos != -1) ? cork->priority: sk->sk_priority;
13351340
skb->mark = sk->sk_mark;
13361341
/*
13371342
* 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,
14811486
ipc.addr = daddr;
14821487
ipc.opt = NULL;
14831488
ipc.tx_flags = 0;
1489+
ipc.ttl = 0;
1490+
ipc.tos = -1;
14841491

14851492
if (replyopts.opt.opt.optlen) {
14861493
ipc.opt = &replyopts.opt;

net/ipv4/ping.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,8 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
713713
ipc.opt = NULL;
714714
ipc.oif = sk->sk_bound_dev_if;
715715
ipc.tx_flags = 0;
716+
ipc.ttl = 0;
717+
ipc.tos = -1;
716718

717719
sock_tx_timestamp(sk, &ipc.tx_flags);
718720

@@ -744,7 +746,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
744746
return -EINVAL;
745747
faddr = ipc.opt->opt.faddr;
746748
}
747-
tos = RT_TOS(inet->tos);
749+
tos = get_rttos(&ipc, inet);
748750
if (sock_flag(sk, SOCK_LOCALROUTE) ||
749751
(msg->msg_flags & MSG_DONTROUTE) ||
750752
(ipc.opt && ipc.opt->opt.is_strictroute)) {

net/ipv4/raw.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
517517
ipc.addr = inet->inet_saddr;
518518
ipc.opt = NULL;
519519
ipc.tx_flags = 0;
520+
ipc.ttl = 0;
521+
ipc.tos = -1;
520522
ipc.oif = sk->sk_bound_dev_if;
521523

522524
if (msg->msg_controllen) {
@@ -556,7 +558,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
556558
daddr = ipc.opt->opt.faddr;
557559
}
558560
}
559-
tos = RT_CONN_FLAGS(sk);
561+
tos = get_rtconn_flags(&ipc, sk);
560562
if (msg->msg_flags & MSG_DONTROUTE)
561563
tos |= RTO_ONLINK;
562564

net/ipv4/udp.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
855855

856856
ipc.opt = NULL;
857857
ipc.tx_flags = 0;
858+
ipc.ttl = 0;
859+
ipc.tos = -1;
858860

859861
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
860862

@@ -938,7 +940,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
938940
faddr = ipc.opt->opt.faddr;
939941
connected = 0;
940942
}
941-
tos = RT_TOS(inet->tos);
943+
tos = get_rttos(&ipc, inet);
942944
if (sock_flag(sk, SOCK_LOCALROUTE) ||
943945
(msg->msg_flags & MSG_DONTROUTE) ||
944946
(ipc.opt && ipc.opt->opt.is_strictroute)) {

0 commit comments

Comments
 (0)