From patchwork Thu Nov 29 01:56:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Paasch X-Patchwork-Id: 1004980 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=apple.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=apple.com header.i=@apple.com header.b="B8q5ZyVD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4350y91DM1z9s3l for ; Thu, 29 Nov 2018 12:57:05 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727312AbeK2NAm (ORCPT ); Thu, 29 Nov 2018 08:00:42 -0500 Received: from nwk-aaemail-lapp01.apple.com ([17.151.62.66]:43768 "EHLO nwk-aaemail-lapp01.apple.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726795AbeK2NAm (ORCPT ); Thu, 29 Nov 2018 08:00:42 -0500 Received: from pps.filterd (nwk-aaemail-lapp01.apple.com [127.0.0.1]) by nwk-aaemail-lapp01.apple.com (8.16.0.22/8.16.0.22) with SMTP id wAT1q4SY005749; Wed, 28 Nov 2018 17:56:58 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apple.com; h=content-transfer-encoding : sender : from : to : cc : subject : date : message-id; s=20180706; bh=knqXe1JGkOul4Ua2H8vnB2M5oLezRixVN89LThHjHo0=; b=B8q5ZyVDmwkHs0aB9+PvdQy1iu4qOxJIdYq5Fo7ZbbxsiqLW6KCFwb7IINOtvSX88gYW vKrfEHD/Wn+PIhJ94iqc3mEWRIsbc4hM8VBw2VRWyUFVGhO73wB7TMpjK+mrTkaUg0nF RS3m/v0KO1IHFf5RouovZlRtIh0orlX/MR8NEPnz56IvTkRr9ZHfXdR/IRRJo5rKHABT 3CtvwBM8zX3NO7UBGcS+qh/kspctS3CIxW7OHCEJYIrtEb02clTtBhe2DzXWupNT9U+d qSWy3bidPBZAkWmA9Y1kFDsSxV/zh5kEZZl2KXwNsldq/Kau19k2CD+ejFJDapQ9hFTi 6A== Received: from ma1-mtap-s01.corp.apple.com (ma1-mtap-s01.corp.apple.com [17.40.76.5]) by nwk-aaemail-lapp01.apple.com with ESMTP id 2p0trd5kfd-6 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Wed, 28 Nov 2018 17:56:58 -0800 Content-transfer-encoding: 7BIT Received: from nwk-mmpp-sz13.apple.com (nwk-mmpp-sz13.apple.com [17.128.115.216]) by ma1-mtap-s01.corp.apple.com (Oracle Communications Messaging Server 8.0.2.3.20180614 64bit (built Jun 14 2018)) with ESMTPS id <0PIX0040SMQPS9D0@ma1-mtap-s01.corp.apple.com>; Wed, 28 Nov 2018 17:56:56 -0800 (PST) Received: from process_viserion-daemon.nwk-mmpp-sz13.apple.com by nwk-mmpp-sz13.apple.com (Oracle Communications Messaging Server 8.0.2.3.20180614 64bit (built Jun 14 2018)) id <0PIX00500MG58K00@nwk-mmpp-sz13.apple.com>; Wed, 28 Nov 2018 17:56:53 -0800 (PST) X-Va-A: X-Va-T-CD: 4b1e0bf36502e052fc75ad21b706ed24 X-Va-E-CD: c3601ecf8d67c38b499957a3cfb82bfe X-Va-R-CD: cea50c8c28b42950a8bea75070159fcb X-Va-CD: 0 X-Va-ID: eaf484b1-5f82-4406-8717-3395a07fa11f X-V-A: X-V-T-CD: 5c1d590bbb3e9640019563b4ec412a7e X-V-E-CD: c3601ecf8d67c38b499957a3cfb82bfe X-V-R-CD: cea50c8c28b42950a8bea75070159fcb X-V-CD: 0 X-V-ID: 7c1b5737-29fe-4251-97a5-f27c5a3eb949 Received: from process_milters-daemon.nwk-mmpp-sz13.apple.com by nwk-mmpp-sz13.apple.com (Oracle Communications Messaging Server 8.0.2.3.20180614 64bit (built Jun 14 2018)) id <0PIX00900MQJCN00@nwk-mmpp-sz13.apple.com>; Wed, 28 Nov 2018 17:56:52 -0800 (PST) Authentication-results: corp.apple.com; spf=softfail smtp.mailfrom=cpaasch@apple.com; dmarc=quarantine header.from=apple.com X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-11-29_01:,, signatures=0 Received: from localhost ([17.234.14.80]) by nwk-mmpp-sz13.apple.com (Oracle Communications Messaging Server 8.0.2.3.20180614 64bit (built Jun 14 2018)) with ESMTPSA id <0PIX00JQGMQR1Q20@nwk-mmpp-sz13.apple.com>; Wed, 28 Nov 2018 17:56:52 -0800 (PST) From: Christoph Paasch To: netdev@vger.kernel.org Cc: Ian Swett , Leif Hedstrom , Jana Iyengar , Eric Dumazet Subject: [PATCH] udp: Allow to defer reception until connect() happened Date: Wed, 28 Nov 2018 17:56:26 -0800 Message-id: <20181129015626.85441-1-cpaasch@apple.com> X-Mailer: git-send-email 2.16.2 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-11-29_01:, , signatures=0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org There are use-cases where a host wants to use a UDP socket with a specific 4-tuple. The way to do this is to bind() and then connect() the socket. However, after the bind(), the socket starts receiving data even if it does not match the intended 4-tuple. That is because after the bind() UDP-socket will match in the lookup for all incoming UDP-traffic that has the specific IP/port. This patch prevents any incoming traffic until the connect() system-call is called whenever the app sets the UDP socket-option UDP_WAIT_FOR_CONNECT. Signed-off-by: Christoph Paasch --- Notes: Changes compared to the original RFC-submission: * Make it a UDP-specific socket-option * Rename it to 'wait-for-connect' Wrt to the discussion on the original RFC submission (cfr., https://marc.info/?l=linux-netdev&m=154102843910587&w=2): We believe that this patch is still useful to enable applications to use different models of implementing a UDP-server. For some frameworks it is much easier to have a socket per-connection and thus let the de-multiplexing happen in the kernel instead of the app. include/linux/udp.h | 5 ++++- include/net/udp.h | 1 + include/uapi/linux/udp.h | 1 + net/ipv4/udp.c | 26 +++++++++++++++++++++++++- net/ipv4/udplite.c | 2 +- net/ipv6/udp.c | 15 ++++++++++++++- net/ipv6/udp_impl.h | 1 + net/ipv6/udplite.c | 2 +- 8 files changed, 48 insertions(+), 5 deletions(-) diff --git a/include/linux/udp.h b/include/linux/udp.h index 2725c83395bf..9a715d25ce36 100644 --- a/include/linux/udp.h +++ b/include/linux/udp.h @@ -55,7 +55,10 @@ struct udp_sock { * different encapsulation layer set * this */ - gro_enabled:1; /* Can accept GRO packets */ + gro_enabled:1, /* Can accept GRO packets */ + wait_for_connect:1;/* Wait until app calls connect() + * before accepting incoming data + */ /* * Following member retains the information to create a UDP header * when the socket is uncorked. diff --git a/include/net/udp.h b/include/net/udp.h index fd6d948755c8..b7467a4129b3 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -285,6 +285,7 @@ int udp_get_port(struct sock *sk, unsigned short snum, const struct sock *)); int udp_err(struct sk_buff *, u32); int udp_abort(struct sock *sk, int err); +int udp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len); int udp_push_pending_frames(struct sock *sk); void udp_flush_pending_frames(struct sock *sk); diff --git a/include/uapi/linux/udp.h b/include/uapi/linux/udp.h index 30baccb6c9c4..b61f8e8dd80b 100644 --- a/include/uapi/linux/udp.h +++ b/include/uapi/linux/udp.h @@ -34,6 +34,7 @@ struct udphdr { #define UDP_NO_CHECK6_RX 102 /* Disable accpeting checksum for UDP6 */ #define UDP_SEGMENT 103 /* Set GSO segmentation size */ #define UDP_GRO 104 /* This socket can receive UDP GRO packets */ +#define UDP_WAIT_FOR_CONNECT 105 /* Don't accept incoming data until the app calls connect() */ /* UDP encapsulation types */ #define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index aff2a8e99e01..c5adafcfd52f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -407,6 +407,9 @@ static int compute_score(struct sock *sk, struct net *net, return -1; score += 4; + if (udp_sk(sk)->wait_for_connect) + return -1; + if (sk->sk_incoming_cpu == raw_smp_processor_id()) score++; return score; @@ -2601,6 +2604,10 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, release_sock(sk); break; + case UDP_WAIT_FOR_CONNECT: + up->wait_for_connect = valbool; + break; + /* * UDP-Lite's partial checksum coverage (RFC 3828). */ @@ -2695,6 +2702,10 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname, val = up->gso_size; break; + case UDP_WAIT_FOR_CONNECT: + val = up->wait_for_connect; + break; + /* The following two cannot be changed on UDP sockets, the return is * always 0 (which corresponds to the full checksum coverage of UDP). */ case UDPLITE_SEND_CSCOV: @@ -2779,12 +2790,25 @@ int udp_abort(struct sock *sk, int err) } EXPORT_SYMBOL_GPL(udp_abort); +int udp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + int ret; + + ret = ip4_datagram_connect(sk, uaddr, addr_len); + + if (!ret) + udp_sk(sk)->wait_for_connect = 0; + + return ret; +} +EXPORT_SYMBOL_GPL(udp_v4_connect); + struct proto udp_prot = { .name = "UDP", .owner = THIS_MODULE, .close = udp_lib_close, .pre_connect = udp_pre_connect, - .connect = ip4_datagram_connect, + .connect = udp_v4_connect, .disconnect = udp_disconnect, .ioctl = udp_ioctl, .init = udp_init_sock, diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 39c7f17d916f..22c74822ff30 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -41,7 +41,7 @@ struct proto udplite_prot = { .name = "UDP-Lite", .owner = THIS_MODULE, .close = udp_lib_close, - .connect = ip4_datagram_connect, + .connect = udp_v4_connect, .disconnect = udp_disconnect, .ioctl = udp_ioctl, .init = udplite_sk_init, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 09cba4cfe31f..c3a9101380de 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1681,6 +1681,19 @@ void udp6_proc_exit(struct net *net) } #endif /* CONFIG_PROC_FS */ +int udp_v6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + int ret; + + ret = ip6_datagram_connect(sk, uaddr, addr_len); + + if (!ret) + udp_sk(sk)->wait_for_connect = 0; + + return ret; +} +EXPORT_SYMBOL_GPL(udp_v6_connect); + /* ------------------------------------------------------------------------ */ struct proto udpv6_prot = { @@ -1688,7 +1701,7 @@ struct proto udpv6_prot = { .owner = THIS_MODULE, .close = udp_lib_close, .pre_connect = udpv6_pre_connect, - .connect = ip6_datagram_connect, + .connect = udp_v6_connect, .disconnect = udp_disconnect, .ioctl = udp_ioctl, .init = udp_init_sock, diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index 5730e6503cb4..14e847b63db9 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h @@ -14,6 +14,7 @@ int __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, u8, u8, int, int udp_v6_get_port(struct sock *sk, unsigned short snum); +int udp_v6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); int udpv6_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); int udpv6_setsockopt(struct sock *sk, int level, int optname, diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index a125aebc29e5..035e1b2f2529 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -38,7 +38,7 @@ struct proto udplitev6_prot = { .name = "UDPLITEv6", .owner = THIS_MODULE, .close = udp_lib_close, - .connect = ip6_datagram_connect, + .connect = udp_v6_connect, .disconnect = udp_disconnect, .ioctl = udp_ioctl, .init = udplite_sk_init,