Per-datagram TTL and TOS via sendmsg()
Subsystems (4)
PATCH 1/1 Per-datagram TTL and TOS via sendmsg()
[Hmm, stupid me. Right this time. Sorry for the line noise.]
This patch adds support for specifying IPv4 Time-To-Live (IP_TTL) and/or Type-Of-Service (IP_TOS) values on a per datagram basis through sendmsg() ancilliary data. Until then, it only worked for IPv6 sockets (using IPV6_HOPLIMIT and IPV6_TCLASS).
Signed-off-by Rémi Denis-Courmont <[email protected]>
include/net/inet_sock.h +2 -0
@@ -140,6 +140,8 @@ struct inet_sock {int length;/* Total length of all frames */ __be32 addr;struct flowi fl; +__s16 ttl; +__s16 tos; } cork; };
include/net/ip.h +2 -0
@@ -54,6 +54,8 @@ struct ipcm_cookie__be32 addr;int oif;struct ip_options *opt; +__s16 ttl; +__s16 tos; };#define IPCB (skb) ((struct inet_skb_parm*)((skb)->cb))
net/ipv4/icmp.c +7 -7
@@ -392,8 +392,9 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) icmp_param->data.icmph.checksum =0 ;icmp_out_count (icmp_param->data.icmph.type); - inet->tos =ip_hdr (skb)->tos; daddr = ipc.addr = rt->rt_src; + ipc.tos =ip_hdr (skb)->tos; + ipc.ttl =MULTICAST (daddr) ? inet->mc_ttl : inet->uc_ttl; ipc.opt =NULL ;if (icmp_param->replyopts.optlen) { ipc.opt = &icmp_param->replyopts;
@@ -438,7 +439,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)struct rtable *rt = (struct rtable *)skb_in->dst;struct ipcm_cookie ipc;__be32 saddr; -u8 tos;if (!rt) goto out;
@@ -526,9 +526,9 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) saddr =0 ; } - tos = icmp_pointers[type].error ? ((iph->tos &IPTOS_TOS_MASK ) | -IPTOS_PREC_INTERNETCONTROL ) : - iph->tos; + ipc.tos = icmp_pointers[type].error ? ((iph->tos &IPTOS_TOS_MASK ) | +IPTOS_PREC_INTERNETCONTROL ) : + iph->tos;if (ip_options_echo (&icmp_param.replyopts, skb_in)) goto out_unlock;
@@ -545,7 +545,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) icmp_param.skb = skb_in; icmp_param.offset =skb_network_offset (skb_in);icmp_out_count (icmp_param.data.icmph.type); -inet_sk (icmp_socket->sk)->tos = tos; + ipc.ttl =-1 ; ipc.addr = iph->saddr; ipc.opt = &icmp_param.replyopts;
@@ -557,7 +557,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) icmp_param.replyopts.faddr : iph->saddr, .saddr = saddr, - .tos = RT_TOS(tos) + .tos = RT_TOS(ipc.tos) } }, .proto = IPPROTO_ICMP,
net/ipv4/ip_output.c +8 -3
@@ -806,6 +806,8 @@ int ip_append_data(struct sock *sk,dst_mtu (rt->u.dst.path); inet->cork.rt = rt; inet->cork.length =0 ; + inet->cork.ttl = ipc->ttl; + inet->cork.tos = ipc->tos; sk->sk_sndmsg_page =NULL ; sk->sk_sndmsg_off =0 ;if ((exthdrlen = rt->u.dst.header_len) !=0 ) {
@@ -1233,7 +1235,9 @@ int ip_push_pending_frames(struct sock *sk)if (inet->cork.flags &IPCORK_OPT ) opt = inet->cork.opt; -if (rt->rt_type ==RTN_MULTICAST ) +if (inet->cork.ttl !=-1 ) + ttl = inet->cork.ttl; +else if (rt->rt_type ==RTN_MULTICAST ) ttl = inet->mc_ttl;else ttl =ip_select_ttl (inet, &rt->u.dst);
@@ -1245,7 +1249,7 @@ int ip_push_pending_frames(struct sock *sk) iph->ihl += opt->optlen>>2 ;ip_options_build (skb, opt, inet->cork.addr, rt,0 ); } - iph->tos = inet->tos; + iph->tos = (inet->cork.tos !=-1 ) ? inet->cork.tos : inet->tos; iph->tot_len =htons (skb->len); iph->frag_off = df;ip_select_ident (iph, &rt->u.dst, sk);
@@ -1343,6 +1347,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar daddr = ipc.addr = rt->rt_src; ipc.opt =NULL ; + ipc.tos =ip_hdr (skb)->tos; + ipc.ttl = inet->uc_ttl;if (replyopts.opt.optlen) { ipc.opt = &replyopts.opt;
@@ -1374,7 +1380,6 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arwith locally disabled BH and that sk cannot be already spinlocked. */ bh_lock_sock (sk); - inet->tos =ip_hdr (skb)->tos; sk->sk_priority = skb->priority; sk->sk_protocol =ip_hdr (skb)->protocol; sk->sk_bound_dev_if = arg->bound_dev_if;
net/ipv4/ip_sockglue.c +10 -0
@@ -190,6 +190,16 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) ipc->addr = info->ipi_spec_dst.s_addr;break ; } +case IP_TTL : +if (cmsg->cmsg_len !=CMSG_LEN (sizeof (int ))) +return -EINVAL ; + ipc->ttl = *(int *)CMSG_DATA (cmsg); +break ; +case IP_TOS : +if (cmsg->cmsg_len !=CMSG_LEN (sizeof (int ))) +return -EINVAL ; + ipc->tos = *(int *)CMSG_DATA (cmsg); +break ;default :return -EINVAL ; }
net/ipv4/raw.c +2 -0
@@ -436,6 +436,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ipc.addr = inet->saddr; ipc.opt =NULL ; ipc.oif = sk->sk_bound_dev_if; + ipc.ttl =MULTICAST (daddr) ? inet->mc_ttl : inet->uc_ttl; + ipc.tos = inet->tos;if (msg->msg_controllen) { err =ip_cmsg_send (msg, &ipc);
net/ipv4/udp.c +2 -0
@@ -581,6 +581,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } ipc.addr = inet->saddr; + ipc.ttl =MULTICAST (daddr) ? inet->mc_ttl : inet->uc_ttl; + ipc.tos = inet->tos; ipc.oif = sk->sk_bound_dev_if;if (msg->msg_controllen) { err =ip_cmsg_send (msg, &ipc);
Signature · 2 lines
Rémi Denis-Courmont http://www.remlab.net/