From patchwork Tue Aug 29 22:29:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Delalande X-Patchwork-Id: 807339 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@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; dkim=pass (1024-bit key; unprotected) header.d=arista.com header.i=@arista.com header.b="n0bohDla"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3xhjxg3fpkz9sNc for ; Wed, 30 Aug 2017 08:29:59 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751744AbdH2W35 (ORCPT ); Tue, 29 Aug 2017 18:29:57 -0400 Received: from prod-mx.aristanetworks.com ([162.210.130.12]:25672 "EHLO prod-mx.aristanetworks.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751425AbdH2W3z (ORCPT ); Tue, 29 Aug 2017 18:29:55 -0400 Received: from prod-mx.aristanetworks.com (localhost [127.0.0.1]) by prod-mx.aristanetworks.com (Postfix) with ESMTP id 1CCC995A7; Tue, 29 Aug 2017 15:29:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=AristaCom; t=1504045795; bh=9IiKUSca7j4h2Z9JUr2Ap8TUU/x5tCpWuZnmmb6DyrA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=n0bohDlaqFo64Gslf8TuASYXpYIDJznwxShefcimU156lrBcR8Z1SfesMwHmjFB5k 7/JT4q06DI83auRiYFJcBLVPSBSczaW3Ul0V7GFaY9q4ZWe8KLosHpguQ8Y1bE61iD vqU7xgzUmnd1QE7K0qtUXnJfaYOPc2vYMEdzzlOQ= Received: from visor.sjc.aristanetworks.com (manila-157.sjc.aristanetworks.com [172.20.135.157]) by prod-mx.aristanetworks.com (Postfix) with ESMTP id 103D295A4; Tue, 29 Aug 2017 15:29:55 -0700 (PDT) From: Ivan Delalande To: David Miller Cc: Eric Dumazet , netdev@vger.kernel.org, Ivan Delalande Subject: [PATCH net-next v3 2/2] tcp_diag: report TCP MD5 signing keys and addresses Date: Tue, 29 Aug 2017 15:29:54 -0700 Message-Id: <20170829222954.24863-3-colona@arista.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170829222954.24863-1-colona@arista.com> References: <20170829222954.24863-1-colona@arista.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Report TCP MD5 (RFC2385) signing keys, addresses and address prefixes to processes with CAP_NET_ADMIN requesting INET_DIAG_INFO. Currently it is not possible to retrieve these from the kernel once they have been configured on sockets. Signed-off-by: Ivan Delalande --- include/uapi/linux/inet_diag.h | 1 + net/ipv4/tcp_diag.c | 115 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 110 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h index 678496897a68..f52ff62bfabe 100644 --- a/include/uapi/linux/inet_diag.h +++ b/include/uapi/linux/inet_diag.h @@ -143,6 +143,7 @@ enum { INET_DIAG_MARK, INET_DIAG_BBRINFO, INET_DIAG_CLASS_ID, + INET_DIAG_MD5SIG, __INET_DIAG_MAX, }; diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index a748c74aa8b7..f972f9f7eae4 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c @@ -16,6 +16,7 @@ #include +#include #include static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, @@ -36,6 +37,106 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, tcp_get_info(sk, info); } +#ifdef CONFIG_TCP_MD5SIG +static void inet_diag_md5sig_fill(struct tcp_md5sig *info, + const struct tcp_md5sig_key *key) +{ + #if IS_ENABLED(CONFIG_IPV6) + if (key->family == AF_INET6) { + struct sockaddr_in6 *sin6 = + (struct sockaddr_in6 *)&info->tcpm_addr; + + memcpy(&sin6->sin6_addr, &key->addr.a6, + sizeof(struct in6_addr)); + } else + #endif + { + struct sockaddr_in *sin = + (struct sockaddr_in *)&info->tcpm_addr; + + memcpy(&sin->sin_addr, &key->addr.a4, sizeof(struct in_addr)); + } + + info->tcpm_addr.ss_family = key->family; + info->tcpm_prefixlen = key->prefixlen; + info->tcpm_keylen = key->keylen; + memcpy(info->tcpm_key, key->key, key->keylen); +} + +static int inet_diag_put_md5sig(struct sk_buff *skb, + const struct tcp_md5sig_info *md5sig) +{ + const struct tcp_md5sig_key *key; + struct nlattr *attr; + struct tcp_md5sig *info; + int md5sig_count = 0; + + hlist_for_each_entry_rcu(key, &md5sig->head, node) + md5sig_count++; + if (md5sig_count == 0) + return 0; + + attr = nla_reserve(skb, INET_DIAG_MD5SIG, + md5sig_count * sizeof(struct tcp_md5sig)); + if (!attr) + return -EMSGSIZE; + + info = nla_data(attr); + hlist_for_each_entry_rcu(key, &md5sig->head, node) { + inet_diag_md5sig_fill(info++, key); + if (--md5sig_count == 0) + break; + } + if (md5sig_count > 0) + memset(info, 0, md5sig_count * sizeof(struct tcp_md5sig)); + + return 0; +} +#endif + +static int tcp_diag_get_aux(struct sock *sk, bool net_admin, + struct sk_buff *skb) +{ +#ifdef CONFIG_TCP_MD5SIG + if (net_admin) { + struct tcp_md5sig_info *md5sig; + int err = 0; + + rcu_read_lock(); + md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info); + if (md5sig) + err = inet_diag_put_md5sig(skb, md5sig); + rcu_read_unlock(); + if (err < 0) + return err; + } +#endif + + return 0; +} + +static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin) +{ + size_t size = 0; + +#ifdef CONFIG_TCP_MD5SIG + if (sk_fullsock(sk)) { + const struct tcp_md5sig_info *md5sig; + const struct tcp_md5sig_key *key; + + rcu_read_lock(); + md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info); + if (md5sig) { + hlist_for_each_entry_rcu(key, &md5sig->head, node) + size += sizeof(struct tcp_md5sig); + } + rcu_read_unlock(); + } +#endif + + return size; +} + static void tcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, const struct inet_diag_req_v2 *r, struct nlattr *bc) { @@ -68,13 +169,15 @@ static int tcp_diag_destroy(struct sk_buff *in_skb, #endif static const struct inet_diag_handler tcp_diag_handler = { - .dump = tcp_diag_dump, - .dump_one = tcp_diag_dump_one, - .idiag_get_info = tcp_diag_get_info, - .idiag_type = IPPROTO_TCP, - .idiag_info_size = sizeof(struct tcp_info), + .dump = tcp_diag_dump, + .dump_one = tcp_diag_dump_one, + .idiag_get_info = tcp_diag_get_info, + .idiag_get_aux = tcp_diag_get_aux, + .idiag_get_aux_size = tcp_diag_get_aux_size, + .idiag_type = IPPROTO_TCP, + .idiag_info_size = sizeof(struct tcp_info), #ifdef CONFIG_INET_DIAG_DESTROY - .destroy = tcp_diag_destroy, + .destroy = tcp_diag_destroy, #endif };