aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2014-11-30 22:22:34 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-08 20:20:48 -0500
commit829ae9d611651467fe6cd7be834bd33ca6b28dfe (patch)
treec61fa3c4fcf20e77540eb8090cde1cec49120e7e /net/ipv6
parent7ce875e5ecb8562fd44040f69bda96c999e38bbc (diff)
net-timestamp: allow reading recv cmsg on errqueue with origin tstamp
Allow reading of timestamps and cmsg at the same time on all relevant socket families. One use is to correlate timestamps with egress device, by asking for cmsg IP_PKTINFO. on AF_INET sockets, call the relevant function (ip_cmsg_recv). To avoid changing legacy expectations, only do so if the caller sets a new timestamping flag SOF_TIMESTAMPING_OPT_CMSG. on AF_INET6 sockets, IPV6_PKTINFO and all other recv cmsg are already returned for all origins. only change is to set ifindex, which is not initialized for all error origins. In both cases, only generate the pktinfo message if an ifindex is known. This is not the case for ACK timestamps. The difference between the protocol families is probably a historical accident as a result of the different conditions for generating cmsg in the relevant ip(v6)_recv_error function: ipv4: if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) { ipv6: if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { At one time, this was the same test bar for the ICMP/ICMP6 distinction. This is no longer true. Signed-off-by: Willem de Bruijn <willemb@google.com> ---- Changes v1 -> v2 large rewrite - integrate with existing pktinfo cmsg generation code - on ipv4: only send with new flag, to maintain legacy behavior - on ipv6: send at most a single pktinfo cmsg - on ipv6: initialize fields if not yet initialized The recv cmsg interfaces are also relevant to the discussion of whether looping packet headers is problematic. For v6, cmsgs that identify many headers are already returned. This patch expands that to v4. If it sounds reasonable, I will follow with patches 1. request timestamps without payload with SOF_TIMESTAMPING_OPT_TSONLY (http://patchwork.ozlabs.org/patch/366967/) 2. sysctl to conditionally drop all timestamps that have payload or cmsg from users without CAP_NET_RAW. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/datagram.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index cc1139687fd7..2464a00e36ab 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -325,6 +325,16 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
325 kfree_skb(skb); 325 kfree_skb(skb);
326} 326}
327 327
328static void ip6_datagram_prepare_pktinfo_errqueue(struct sk_buff *skb)
329{
330 int ifindex = skb->dev ? skb->dev->ifindex : -1;
331
332 if (skb->protocol == htons(ETH_P_IPV6))
333 IP6CB(skb)->iif = ifindex;
334 else
335 PKTINFO_SKB_CB(skb)->ipi_ifindex = ifindex;
336}
337
328/* 338/*
329 * Handle MSG_ERRQUEUE 339 * Handle MSG_ERRQUEUE
330 */ 340 */
@@ -388,8 +398,12 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
388 sin->sin6_family = AF_INET6; 398 sin->sin6_family = AF_INET6;
389 sin->sin6_flowinfo = 0; 399 sin->sin6_flowinfo = 0;
390 sin->sin6_port = 0; 400 sin->sin6_port = 0;
391 if (np->rxopt.all) 401 if (np->rxopt.all) {
402 if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP &&
403 serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6)
404 ip6_datagram_prepare_pktinfo_errqueue(skb);
392 ip6_datagram_recv_common_ctl(sk, msg, skb); 405 ip6_datagram_recv_common_ctl(sk, msg, skb);
406 }
393 if (skb->protocol == htons(ETH_P_IPV6)) { 407 if (skb->protocol == htons(ETH_P_IPV6)) {
394 sin->sin6_addr = ipv6_hdr(skb)->saddr; 408 sin->sin6_addr = ipv6_hdr(skb)->saddr;
395 if (np->rxopt.all) 409 if (np->rxopt.all)
@@ -491,7 +505,10 @@ void ip6_datagram_recv_common_ctl(struct sock *sk, struct msghdr *msg,
491 ipv6_addr_set_v4mapped(ip_hdr(skb)->daddr, 505 ipv6_addr_set_v4mapped(ip_hdr(skb)->daddr,
492 &src_info.ipi6_addr); 506 &src_info.ipi6_addr);
493 } 507 }
494 put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); 508
509 if (src_info.ipi6_ifindex >= 0)
510 put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO,
511 sizeof(src_info), &src_info);
495 } 512 }
496} 513}
497 514