mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-24 15:37:13 +07:00
Merge branch 'TIPC-Encryption'
Tuong Lien says: ==================== TIPC Encryption This series provides TIPC encryption feature, kernel part. There will be another one in the 'iproute2/tipc' for user space to set key. v2: add select crypto 'aes(gcm)' for TIPC_CRYPTO in Kconfig ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1c8f11d057
@ -233,6 +233,27 @@ struct tipc_sioc_nodeid_req {
|
||||
char node_id[TIPC_NODEID_LEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* TIPC Crypto, AEAD
|
||||
*/
|
||||
#define TIPC_AEAD_ALG_NAME (32)
|
||||
|
||||
struct tipc_aead_key {
|
||||
char alg_name[TIPC_AEAD_ALG_NAME];
|
||||
unsigned int keylen; /* in bytes */
|
||||
char key[];
|
||||
};
|
||||
|
||||
#define TIPC_AEAD_KEYLEN_MIN (16 + 4)
|
||||
#define TIPC_AEAD_KEYLEN_MAX (32 + 4)
|
||||
#define TIPC_AEAD_KEY_SIZE_MAX (sizeof(struct tipc_aead_key) + \
|
||||
TIPC_AEAD_KEYLEN_MAX)
|
||||
|
||||
static inline int tipc_aead_key_size(struct tipc_aead_key *key)
|
||||
{
|
||||
return sizeof(*key) + key->keylen;
|
||||
}
|
||||
|
||||
/* The macros and functions below are deprecated:
|
||||
*/
|
||||
|
||||
|
@ -63,6 +63,8 @@ enum {
|
||||
TIPC_NL_PEER_REMOVE,
|
||||
TIPC_NL_BEARER_ADD,
|
||||
TIPC_NL_UDP_GET_REMOTEIP,
|
||||
TIPC_NL_KEY_SET,
|
||||
TIPC_NL_KEY_FLUSH,
|
||||
|
||||
__TIPC_NL_CMD_MAX,
|
||||
TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
|
||||
@ -160,6 +162,8 @@ enum {
|
||||
TIPC_NLA_NODE_UNSPEC,
|
||||
TIPC_NLA_NODE_ADDR, /* u32 */
|
||||
TIPC_NLA_NODE_UP, /* flag */
|
||||
TIPC_NLA_NODE_ID, /* data */
|
||||
TIPC_NLA_NODE_KEY, /* data */
|
||||
|
||||
__TIPC_NLA_NODE_MAX,
|
||||
TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1
|
||||
|
@ -35,6 +35,21 @@ config TIPC_MEDIA_UDP
|
||||
Saying Y here will enable support for running TIPC over IP/UDP
|
||||
bool
|
||||
default y
|
||||
config TIPC_CRYPTO
|
||||
bool "TIPC encryption support"
|
||||
depends on TIPC
|
||||
select CRYPTO
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_GCM
|
||||
help
|
||||
Saying Y here will enable support for TIPC encryption.
|
||||
All TIPC messages will be encrypted/decrypted by using the currently most
|
||||
advanced algorithm: AEAD AES-GCM (like IPSec or TLS) before leaving/
|
||||
entering the TIPC stack.
|
||||
Key setting from user-space is performed via netlink by a user program
|
||||
(e.g. the iproute2 'tipc' tool).
|
||||
bool
|
||||
default y
|
||||
|
||||
config TIPC_DIAG
|
||||
tristate "TIPC: socket monitoring interface"
|
||||
|
@ -16,6 +16,7 @@ CFLAGS_trace.o += -I$(src)
|
||||
tipc-$(CONFIG_TIPC_MEDIA_UDP) += udp_media.o
|
||||
tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o
|
||||
tipc-$(CONFIG_SYSCTL) += sysctl.o
|
||||
tipc-$(CONFIG_TIPC_CRYPTO) += crypto.o
|
||||
|
||||
|
||||
obj-$(CONFIG_TIPC_DIAG) += diag.o
|
||||
|
@ -84,7 +84,7 @@ static struct tipc_bc_base *tipc_bc_base(struct net *net)
|
||||
*/
|
||||
int tipc_bcast_get_mtu(struct net *net)
|
||||
{
|
||||
return tipc_link_mtu(tipc_bc_sndlink(net)) - INT_H_SIZE;
|
||||
return tipc_link_mss(tipc_bc_sndlink(net));
|
||||
}
|
||||
|
||||
void tipc_bcast_disable_rcast(struct net *net)
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "netlink.h"
|
||||
#include "udp_media.h"
|
||||
#include "trace.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#define MAX_ADDR_STR 60
|
||||
|
||||
@ -315,6 +316,7 @@ static int tipc_enable_bearer(struct net *net, const char *name,
|
||||
b->net_plane = bearer_id + 'A';
|
||||
b->priority = prio;
|
||||
test_and_set_bit_lock(0, &b->up);
|
||||
refcount_set(&b->refcnt, 1);
|
||||
|
||||
res = tipc_disc_create(net, b, &b->bcast_addr, &skb);
|
||||
if (res) {
|
||||
@ -351,6 +353,17 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tipc_bearer_hold(struct tipc_bearer *b)
|
||||
{
|
||||
return (b && refcount_inc_not_zero(&b->refcnt));
|
||||
}
|
||||
|
||||
void tipc_bearer_put(struct tipc_bearer *b)
|
||||
{
|
||||
if (b && refcount_dec_and_test(&b->refcnt))
|
||||
kfree_rcu(b, rcu);
|
||||
}
|
||||
|
||||
/**
|
||||
* bearer_disable
|
||||
*
|
||||
@ -369,7 +382,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b)
|
||||
if (b->disc)
|
||||
tipc_disc_delete(b->disc);
|
||||
RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL);
|
||||
kfree_rcu(b, rcu);
|
||||
tipc_bearer_put(b);
|
||||
tipc_mon_delete(net, bearer_id);
|
||||
}
|
||||
|
||||
@ -504,10 +517,15 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
|
||||
|
||||
rcu_read_lock();
|
||||
b = bearer_get(net, bearer_id);
|
||||
if (likely(b && (test_bit(0, &b->up) || msg_is_reset(hdr))))
|
||||
b->media->send_msg(net, skb, b, dest);
|
||||
else
|
||||
if (likely(b && (test_bit(0, &b->up) || msg_is_reset(hdr)))) {
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
tipc_crypto_xmit(net, &skb, b, dest, NULL);
|
||||
if (skb)
|
||||
#endif
|
||||
b->media->send_msg(net, skb, b, dest);
|
||||
} else {
|
||||
kfree_skb(skb);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@ -515,7 +533,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
|
||||
*/
|
||||
void tipc_bearer_xmit(struct net *net, u32 bearer_id,
|
||||
struct sk_buff_head *xmitq,
|
||||
struct tipc_media_addr *dst)
|
||||
struct tipc_media_addr *dst,
|
||||
struct tipc_node *__dnode)
|
||||
{
|
||||
struct tipc_bearer *b;
|
||||
struct sk_buff *skb, *tmp;
|
||||
@ -529,10 +548,15 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,
|
||||
__skb_queue_purge(xmitq);
|
||||
skb_queue_walk_safe(xmitq, skb, tmp) {
|
||||
__skb_dequeue(xmitq);
|
||||
if (likely(test_bit(0, &b->up) || msg_is_reset(buf_msg(skb))))
|
||||
b->media->send_msg(net, skb, b, dst);
|
||||
else
|
||||
if (likely(test_bit(0, &b->up) || msg_is_reset(buf_msg(skb)))) {
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
tipc_crypto_xmit(net, &skb, b, dst, __dnode);
|
||||
if (skb)
|
||||
#endif
|
||||
b->media->send_msg(net, skb, b, dst);
|
||||
} else {
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@ -543,6 +567,7 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
|
||||
struct sk_buff_head *xmitq)
|
||||
{
|
||||
struct tipc_net *tn = tipc_net(net);
|
||||
struct tipc_media_addr *dst;
|
||||
int net_id = tn->net_id;
|
||||
struct tipc_bearer *b;
|
||||
struct sk_buff *skb, *tmp;
|
||||
@ -557,7 +582,12 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
|
||||
msg_set_non_seq(hdr, 1);
|
||||
msg_set_mc_netid(hdr, net_id);
|
||||
__skb_dequeue(xmitq);
|
||||
b->media->send_msg(net, skb, b, &b->bcast_addr);
|
||||
dst = &b->bcast_addr;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
tipc_crypto_xmit(net, &skb, b, dst, NULL);
|
||||
if (skb)
|
||||
#endif
|
||||
b->media->send_msg(net, skb, b, dst);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@ -584,6 +614,7 @@ static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev,
|
||||
if (likely(b && test_bit(0, &b->up) &&
|
||||
(skb->pkt_type <= PACKET_MULTICAST))) {
|
||||
skb_mark_not_on_list(skb);
|
||||
TIPC_SKB_CB(skb)->flags = 0;
|
||||
tipc_rcv(dev_net(b->pt.dev), skb, b);
|
||||
rcu_read_unlock();
|
||||
return NET_RX_SUCCESS;
|
||||
|
@ -165,6 +165,7 @@ struct tipc_bearer {
|
||||
struct tipc_discoverer *disc;
|
||||
char net_plane;
|
||||
unsigned long up;
|
||||
refcount_t refcnt;
|
||||
};
|
||||
|
||||
struct tipc_bearer_names {
|
||||
@ -210,6 +211,8 @@ int tipc_media_set_window(const char *name, u32 new_value);
|
||||
int tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
|
||||
int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
|
||||
struct nlattr *attrs[]);
|
||||
bool tipc_bearer_hold(struct tipc_bearer *b);
|
||||
void tipc_bearer_put(struct tipc_bearer *b);
|
||||
void tipc_disable_l2_media(struct tipc_bearer *b);
|
||||
int tipc_l2_send_msg(struct net *net, struct sk_buff *buf,
|
||||
struct tipc_bearer *b, struct tipc_media_addr *dest);
|
||||
@ -229,7 +232,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
|
||||
struct tipc_media_addr *dest);
|
||||
void tipc_bearer_xmit(struct net *net, u32 bearer_id,
|
||||
struct sk_buff_head *xmitq,
|
||||
struct tipc_media_addr *dst);
|
||||
struct tipc_media_addr *dst,
|
||||
struct tipc_node *__dnode);
|
||||
void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
|
||||
struct sk_buff_head *xmitq);
|
||||
void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts);
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "socket.h"
|
||||
#include "bcast.h"
|
||||
#include "node.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
@ -68,6 +69,11 @@ static int __net_init tipc_init_net(struct net *net)
|
||||
INIT_LIST_HEAD(&tn->node_list);
|
||||
spin_lock_init(&tn->node_list_lock);
|
||||
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
err = tipc_crypto_start(&tn->crypto_tx, net, NULL);
|
||||
if (err)
|
||||
goto out_crypto;
|
||||
#endif
|
||||
err = tipc_sk_rht_init(net);
|
||||
if (err)
|
||||
goto out_sk_rht;
|
||||
@ -93,6 +99,11 @@ static int __net_init tipc_init_net(struct net *net)
|
||||
out_nametbl:
|
||||
tipc_sk_rht_destroy(net);
|
||||
out_sk_rht:
|
||||
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
tipc_crypto_stop(&tn->crypto_tx);
|
||||
out_crypto:
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -103,6 +114,9 @@ static void __net_exit tipc_exit_net(struct net *net)
|
||||
tipc_bcast_stop(net);
|
||||
tipc_nametbl_stop(net);
|
||||
tipc_sk_rht_destroy(net);
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
tipc_crypto_stop(&tipc_net(net)->crypto_tx);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __net_exit tipc_pernet_pre_exit(struct net *net)
|
||||
|
@ -68,6 +68,9 @@ struct tipc_link;
|
||||
struct tipc_name_table;
|
||||
struct tipc_topsrv;
|
||||
struct tipc_monitor;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
struct tipc_crypto;
|
||||
#endif
|
||||
|
||||
#define TIPC_MOD_VER "2.0.0"
|
||||
|
||||
@ -129,6 +132,11 @@ struct tipc_net {
|
||||
|
||||
/* Tracing of node internal messages */
|
||||
struct packet_type loopback_pt;
|
||||
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
/* TX crypto handler */
|
||||
struct tipc_crypto *crypto_tx;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline struct tipc_net *tipc_net(struct net *net)
|
||||
|
1986
net/tipc/crypto.c
Normal file
1986
net/tipc/crypto.c
Normal file
File diff suppressed because it is too large
Load Diff
167
net/tipc/crypto.h
Normal file
167
net/tipc/crypto.h
Normal file
@ -0,0 +1,167 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/**
|
||||
* net/tipc/crypto.h: Include file for TIPC crypto
|
||||
*
|
||||
* Copyright (c) 2019, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
#ifndef _TIPC_CRYPTO_H
|
||||
#define _TIPC_CRYPTO_H
|
||||
|
||||
#include "core.h"
|
||||
#include "node.h"
|
||||
#include "msg.h"
|
||||
#include "bearer.h"
|
||||
|
||||
#define TIPC_EVERSION 7
|
||||
|
||||
/* AEAD aes(gcm) */
|
||||
#define TIPC_AES_GCM_KEY_SIZE_128 16
|
||||
#define TIPC_AES_GCM_KEY_SIZE_192 24
|
||||
#define TIPC_AES_GCM_KEY_SIZE_256 32
|
||||
|
||||
#define TIPC_AES_GCM_SALT_SIZE 4
|
||||
#define TIPC_AES_GCM_IV_SIZE 12
|
||||
#define TIPC_AES_GCM_TAG_SIZE 16
|
||||
|
||||
/**
|
||||
* TIPC crypto modes:
|
||||
* - CLUSTER_KEY:
|
||||
* One single key is used for both TX & RX in all nodes in the cluster.
|
||||
* - PER_NODE_KEY:
|
||||
* Each nodes in the cluster has one TX key, for RX a node needs to know
|
||||
* its peers' TX key for the decryption of messages from those nodes.
|
||||
*/
|
||||
enum {
|
||||
CLUSTER_KEY = 1,
|
||||
PER_NODE_KEY = (1 << 1),
|
||||
};
|
||||
|
||||
extern int sysctl_tipc_max_tfms __read_mostly;
|
||||
|
||||
/**
|
||||
* TIPC encryption message format:
|
||||
*
|
||||
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
|
||||
* 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* w0:|Ver=7| User |D|TX |RX |K| Rsvd |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* w1:| Seqno |
|
||||
* w2:| (8 octets) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* w3:\ Prevnode \
|
||||
* / (4 or 16 octets) /
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* \ \
|
||||
* / Encrypted complete TIPC V2 header and user data /
|
||||
* \ \
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | |
|
||||
* | AuthTag |
|
||||
* | (16 octets) |
|
||||
* | |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* Word0:
|
||||
* Ver : = 7 i.e. TIPC encryption message version
|
||||
* User : = 7 (for LINK_PROTOCOL); = 13 (for LINK_CONFIG) or = 0
|
||||
* D : The destined bit i.e. the message's destination node is
|
||||
* "known" or not at the message encryption
|
||||
* TX : TX key used for the message encryption
|
||||
* RX : Currently RX active key corresponding to the destination
|
||||
* node's TX key (when the "D" bit is set)
|
||||
* K : Keep-alive bit (for RPS, LINK_PROTOCOL/STATE_MSG only)
|
||||
* Rsvd : Reserved bit, field
|
||||
* Word1-2:
|
||||
* Seqno : The 64-bit sequence number of the encrypted message, also
|
||||
* part of the nonce used for the message encryption/decryption
|
||||
* Word3-:
|
||||
* Prevnode: The source node address, or ID in case LINK_CONFIG only
|
||||
* AuthTag : The authentication tag for the message integrity checking
|
||||
* generated by the message encryption
|
||||
*/
|
||||
struct tipc_ehdr {
|
||||
union {
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
__u8 destined:1,
|
||||
user:4,
|
||||
version:3;
|
||||
__u8 reserved_1:3,
|
||||
keepalive:1,
|
||||
rx_key_active:2,
|
||||
tx_key:2;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
__u8 version:3,
|
||||
user:4,
|
||||
destined:1;
|
||||
__u8 tx_key:2,
|
||||
rx_key_active:2,
|
||||
keepalive:1,
|
||||
reserved_1:3;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
__be16 reserved_2;
|
||||
} __packed;
|
||||
__be32 w0;
|
||||
};
|
||||
__be64 seqno;
|
||||
union {
|
||||
__be32 addr;
|
||||
__u8 id[NODE_ID_LEN]; /* For a LINK_CONFIG message only! */
|
||||
};
|
||||
#define EHDR_SIZE (offsetof(struct tipc_ehdr, addr) + sizeof(__be32))
|
||||
#define EHDR_CFG_SIZE (sizeof(struct tipc_ehdr))
|
||||
#define EHDR_MIN_SIZE (EHDR_SIZE)
|
||||
#define EHDR_MAX_SIZE (EHDR_CFG_SIZE)
|
||||
#define EMSG_OVERHEAD (EHDR_SIZE + TIPC_AES_GCM_TAG_SIZE)
|
||||
} __packed;
|
||||
|
||||
int tipc_crypto_start(struct tipc_crypto **crypto, struct net *net,
|
||||
struct tipc_node *node);
|
||||
void tipc_crypto_stop(struct tipc_crypto **crypto);
|
||||
void tipc_crypto_timeout(struct tipc_crypto *rx);
|
||||
int tipc_crypto_xmit(struct net *net, struct sk_buff **skb,
|
||||
struct tipc_bearer *b, struct tipc_media_addr *dst,
|
||||
struct tipc_node *__dnode);
|
||||
int tipc_crypto_rcv(struct net *net, struct tipc_crypto *rx,
|
||||
struct sk_buff **skb, struct tipc_bearer *b);
|
||||
int tipc_crypto_key_init(struct tipc_crypto *c, struct tipc_aead_key *ukey,
|
||||
u8 mode);
|
||||
void tipc_crypto_key_flush(struct tipc_crypto *c);
|
||||
int tipc_aead_key_validate(struct tipc_aead_key *ukey);
|
||||
bool tipc_ehdr_validate(struct sk_buff *skb);
|
||||
|
||||
#endif /* _TIPC_CRYPTO_H */
|
||||
#endif
|
@ -44,6 +44,7 @@
|
||||
#include "netlink.h"
|
||||
#include "monitor.h"
|
||||
#include "trace.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include <linux/pkt_sched.h>
|
||||
|
||||
@ -397,6 +398,15 @@ int tipc_link_mtu(struct tipc_link *l)
|
||||
return l->mtu;
|
||||
}
|
||||
|
||||
int tipc_link_mss(struct tipc_link *l)
|
||||
{
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
return l->mtu - INT_H_SIZE - EMSG_OVERHEAD;
|
||||
#else
|
||||
return l->mtu - INT_H_SIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
u16 tipc_link_rcv_nxt(struct tipc_link *l)
|
||||
{
|
||||
return l->rcv_nxt;
|
||||
@ -948,6 +958,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
|
||||
u16 seqno = l->snd_nxt;
|
||||
int pkt_cnt = skb_queue_len(list);
|
||||
int imp = msg_importance(hdr);
|
||||
unsigned int mss = tipc_link_mss(l);
|
||||
unsigned int maxwin = l->window;
|
||||
unsigned int mtu = l->mtu;
|
||||
bool new_bundle;
|
||||
@ -1000,8 +1011,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
|
||||
continue;
|
||||
}
|
||||
if (tipc_msg_try_bundle(l->backlog[imp].target_bskb, &skb,
|
||||
mtu - INT_H_SIZE, l->addr,
|
||||
&new_bundle)) {
|
||||
mss, l->addr, &new_bundle)) {
|
||||
if (skb) {
|
||||
/* Keep a ref. to the skb for next try */
|
||||
l->backlog[imp].target_bskb = skb;
|
||||
@ -1154,7 +1164,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
|
||||
if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
|
||||
continue;
|
||||
TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
|
||||
_skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC);
|
||||
_skb = pskb_copy(skb, GFP_ATOMIC);
|
||||
if (!_skb)
|
||||
return 0;
|
||||
hdr = buf_msg(_skb);
|
||||
@ -1430,8 +1440,7 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
|
||||
if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
|
||||
continue;
|
||||
TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
|
||||
_skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE,
|
||||
GFP_ATOMIC);
|
||||
_skb = pskb_copy(skb, GFP_ATOMIC);
|
||||
if (!_skb)
|
||||
continue;
|
||||
hdr = buf_msg(_skb);
|
||||
|
@ -141,6 +141,7 @@ void tipc_link_remove_bc_peer(struct tipc_link *snd_l,
|
||||
int tipc_link_bc_peers(struct tipc_link *l);
|
||||
void tipc_link_set_mtu(struct tipc_link *l, int mtu);
|
||||
int tipc_link_mtu(struct tipc_link *l);
|
||||
int tipc_link_mss(struct tipc_link *l);
|
||||
void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
|
||||
struct sk_buff_head *xmitq);
|
||||
void tipc_link_build_bc_sync_msg(struct tipc_link *l,
|
||||
|
@ -39,10 +39,16 @@
|
||||
#include "msg.h"
|
||||
#include "addr.h"
|
||||
#include "name_table.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#define MAX_FORWARD_SIZE 1024
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
#define BUF_HEADROOM ALIGN(((LL_MAX_HEADER + 48) + EHDR_MAX_SIZE), 16)
|
||||
#define BUF_TAILROOM (TIPC_AES_GCM_TAG_SIZE)
|
||||
#else
|
||||
#define BUF_HEADROOM (LL_MAX_HEADER + 48)
|
||||
#define BUF_TAILROOM 16
|
||||
#endif
|
||||
|
||||
static unsigned int align(unsigned int i)
|
||||
{
|
||||
@ -61,7 +67,11 @@ static unsigned int align(unsigned int i)
|
||||
struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
unsigned int buf_size = (BUF_HEADROOM + size + BUF_TAILROOM + 3) & ~3u;
|
||||
#else
|
||||
unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
|
||||
#endif
|
||||
|
||||
skb = alloc_skb_fclone(buf_size, gfp);
|
||||
if (skb) {
|
||||
@ -173,7 +183,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
|
||||
}
|
||||
|
||||
if (fragid == LAST_FRAGMENT) {
|
||||
TIPC_SKB_CB(head)->validated = false;
|
||||
TIPC_SKB_CB(head)->validated = 0;
|
||||
if (unlikely(!tipc_msg_validate(&head)))
|
||||
goto err;
|
||||
*buf = head;
|
||||
@ -271,6 +281,7 @@ bool tipc_msg_validate(struct sk_buff **_skb)
|
||||
|
||||
if (unlikely(TIPC_SKB_CB(skb)->validated))
|
||||
return true;
|
||||
|
||||
if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE)))
|
||||
return false;
|
||||
|
||||
@ -292,7 +303,7 @@ bool tipc_msg_validate(struct sk_buff **_skb)
|
||||
if (unlikely(skb->len < msz))
|
||||
return false;
|
||||
|
||||
TIPC_SKB_CB(skb)->validated = true;
|
||||
TIPC_SKB_CB(skb)->validated = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,16 +102,42 @@ struct plist;
|
||||
#define TIPC_MEDIA_INFO_OFFSET 5
|
||||
|
||||
struct tipc_skb_cb {
|
||||
struct sk_buff *tail;
|
||||
unsigned long nxt_retr;
|
||||
unsigned long retr_stamp;
|
||||
u32 bytes_read;
|
||||
u32 orig_member;
|
||||
u16 chain_imp;
|
||||
u16 ackers;
|
||||
u16 retr_cnt;
|
||||
bool validated;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
struct sk_buff *tail;
|
||||
unsigned long nxt_retr;
|
||||
unsigned long retr_stamp;
|
||||
u32 bytes_read;
|
||||
u32 orig_member;
|
||||
u16 chain_imp;
|
||||
u16 ackers;
|
||||
u16 retr_cnt;
|
||||
} __packed;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
struct {
|
||||
struct tipc_crypto *rx;
|
||||
struct tipc_aead *last;
|
||||
u8 recurs;
|
||||
} tx_clone_ctx __packed;
|
||||
#endif
|
||||
} __packed;
|
||||
union {
|
||||
struct {
|
||||
u8 validated:1;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
u8 encrypted:1;
|
||||
u8 decrypted:1;
|
||||
u8 probe:1;
|
||||
u8 tx_clone_deferred:1;
|
||||
#endif
|
||||
};
|
||||
u8 flags;
|
||||
};
|
||||
u8 reserved;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
void *crypto_ctx;
|
||||
#endif
|
||||
} __packed;
|
||||
|
||||
#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
|
||||
|
||||
|
@ -102,7 +102,11 @@ const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = {
|
||||
const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
|
||||
[TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC },
|
||||
[TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 },
|
||||
[TIPC_NLA_NODE_UP] = { .type = NLA_FLAG }
|
||||
[TIPC_NLA_NODE_UP] = { .type = NLA_FLAG },
|
||||
[TIPC_NLA_NODE_ID] = { .type = NLA_BINARY,
|
||||
.len = TIPC_NODEID_LEN},
|
||||
[TIPC_NLA_NODE_KEY] = { .type = NLA_BINARY,
|
||||
.len = TIPC_AEAD_KEY_SIZE_MAX},
|
||||
};
|
||||
|
||||
/* Properties valid for media, bearer and link */
|
||||
@ -257,6 +261,18 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
|
||||
.dumpit = tipc_udp_nl_dump_remoteip,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
{
|
||||
.cmd = TIPC_NL_KEY_SET,
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
.doit = tipc_nl_node_set_key,
|
||||
},
|
||||
{
|
||||
.cmd = TIPC_NL_KEY_FLUSH,
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
.doit = tipc_nl_node_flush_key,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
struct genl_family tipc_genl_family __ro_after_init = {
|
||||
|
327
net/tipc/node.c
327
net/tipc/node.c
@ -44,6 +44,7 @@
|
||||
#include "discover.h"
|
||||
#include "netlink.h"
|
||||
#include "trace.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#define INVALID_NODE_SIG 0x10000
|
||||
#define NODE_CLEANUP_AFTER 300000
|
||||
@ -89,6 +90,7 @@ struct tipc_bclink_entry {
|
||||
* @links: array containing references to all links to node
|
||||
* @action_flags: bit mask of different types of node actions
|
||||
* @state: connectivity state vs peer node
|
||||
* @preliminary: a preliminary node or not
|
||||
* @sync_point: sequence number where synch/failover is finished
|
||||
* @list: links to adjacent nodes in sorted list of cluster's nodes
|
||||
* @working_links: number of working links to node (both active and standby)
|
||||
@ -99,6 +101,7 @@ struct tipc_bclink_entry {
|
||||
* @publ_list: list of publications
|
||||
* @rcu: rcu struct for tipc_node
|
||||
* @delete_at: indicates the time for deleting a down node
|
||||
* @crypto_rx: RX crypto handler
|
||||
*/
|
||||
struct tipc_node {
|
||||
u32 addr;
|
||||
@ -112,6 +115,7 @@ struct tipc_node {
|
||||
int action_flags;
|
||||
struct list_head list;
|
||||
int state;
|
||||
bool preliminary;
|
||||
bool failover_sent;
|
||||
u16 sync_point;
|
||||
int link_cnt;
|
||||
@ -120,6 +124,7 @@ struct tipc_node {
|
||||
u32 signature;
|
||||
u32 link_id;
|
||||
u8 peer_id[16];
|
||||
char peer_id_string[NODE_ID_STR_LEN];
|
||||
struct list_head publ_list;
|
||||
struct list_head conn_sks;
|
||||
unsigned long keepalive_intv;
|
||||
@ -128,6 +133,9 @@ struct tipc_node {
|
||||
unsigned long delete_at;
|
||||
struct net *peer_net;
|
||||
u32 peer_hash_mix;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
struct tipc_crypto *crypto_rx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Node FSM states and events:
|
||||
@ -165,7 +173,6 @@ static void tipc_node_timeout(struct timer_list *t);
|
||||
static void tipc_node_fsm_evt(struct tipc_node *n, int evt);
|
||||
static struct tipc_node *tipc_node_find(struct net *net, u32 addr);
|
||||
static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id);
|
||||
static void tipc_node_put(struct tipc_node *node);
|
||||
static bool node_is_up(struct tipc_node *n);
|
||||
static void tipc_node_delete_from_list(struct tipc_node *node);
|
||||
|
||||
@ -245,15 +252,51 @@ u16 tipc_node_get_capabilities(struct net *net, u32 addr)
|
||||
return caps;
|
||||
}
|
||||
|
||||
u32 tipc_node_get_addr(struct tipc_node *node)
|
||||
{
|
||||
return (node) ? node->addr : 0;
|
||||
}
|
||||
|
||||
char *tipc_node_get_id_str(struct tipc_node *node)
|
||||
{
|
||||
return node->peer_id_string;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
/**
|
||||
* tipc_node_crypto_rx - Retrieve crypto RX handle from node
|
||||
* Note: node ref counter must be held first!
|
||||
*/
|
||||
struct tipc_crypto *tipc_node_crypto_rx(struct tipc_node *__n)
|
||||
{
|
||||
return (__n) ? __n->crypto_rx : NULL;
|
||||
}
|
||||
|
||||
struct tipc_crypto *tipc_node_crypto_rx_by_list(struct list_head *pos)
|
||||
{
|
||||
return container_of(pos, struct tipc_node, list)->crypto_rx;
|
||||
}
|
||||
#endif
|
||||
|
||||
void tipc_node_free(struct rcu_head *rp)
|
||||
{
|
||||
struct tipc_node *n = container_of(rp, struct tipc_node, rcu);
|
||||
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
tipc_crypto_stop(&n->crypto_rx);
|
||||
#endif
|
||||
kfree(n);
|
||||
}
|
||||
|
||||
static void tipc_node_kref_release(struct kref *kref)
|
||||
{
|
||||
struct tipc_node *n = container_of(kref, struct tipc_node, kref);
|
||||
|
||||
kfree(n->bc_entry.link);
|
||||
kfree_rcu(n, rcu);
|
||||
call_rcu(&n->rcu, tipc_node_free);
|
||||
}
|
||||
|
||||
static void tipc_node_put(struct tipc_node *node)
|
||||
void tipc_node_put(struct tipc_node *node)
|
||||
{
|
||||
kref_put(&node->kref, tipc_node_kref_release);
|
||||
}
|
||||
@ -274,7 +317,7 @@ static struct tipc_node *tipc_node_find(struct net *net, u32 addr)
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(node, &tn->node_htable[thash], hash) {
|
||||
if (node->addr != addr)
|
||||
if (node->addr != addr || node->preliminary)
|
||||
continue;
|
||||
if (!kref_get_unless_zero(&node->kref))
|
||||
node = NULL;
|
||||
@ -398,19 +441,41 @@ static void tipc_node_assign_peer_net(struct tipc_node *n, u32 hash_mixes)
|
||||
}
|
||||
}
|
||||
|
||||
static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
|
||||
u8 *peer_id, u16 capabilities,
|
||||
u32 signature, u32 hash_mixes)
|
||||
struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
|
||||
u16 capabilities, u32 hash_mixes,
|
||||
bool preliminary)
|
||||
{
|
||||
struct tipc_net *tn = net_generic(net, tipc_net_id);
|
||||
struct tipc_node *n, *temp_node;
|
||||
struct tipc_link *l;
|
||||
unsigned long intv;
|
||||
int bearer_id;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&tn->node_list_lock);
|
||||
n = tipc_node_find(net, addr);
|
||||
n = tipc_node_find(net, addr) ?:
|
||||
tipc_node_find_by_id(net, peer_id);
|
||||
if (n) {
|
||||
if (!n->preliminary)
|
||||
goto update;
|
||||
if (preliminary)
|
||||
goto exit;
|
||||
/* A preliminary node becomes "real" now, refresh its data */
|
||||
tipc_node_write_lock(n);
|
||||
n->preliminary = false;
|
||||
n->addr = addr;
|
||||
hlist_del_rcu(&n->hash);
|
||||
hlist_add_head_rcu(&n->hash,
|
||||
&tn->node_htable[tipc_hashfn(addr)]);
|
||||
list_del_rcu(&n->list);
|
||||
list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
|
||||
if (n->addr < temp_node->addr)
|
||||
break;
|
||||
}
|
||||
list_add_tail_rcu(&n->list, &temp_node->list);
|
||||
tipc_node_write_unlock_fast(n);
|
||||
|
||||
update:
|
||||
if (n->peer_hash_mix ^ hash_mixes)
|
||||
tipc_node_assign_peer_net(n, hash_mixes);
|
||||
if (n->capabilities == capabilities)
|
||||
@ -438,7 +503,17 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
|
||||
pr_warn("Node creation failed, no memory\n");
|
||||
goto exit;
|
||||
}
|
||||
tipc_nodeid2string(n->peer_id_string, peer_id);
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
if (unlikely(tipc_crypto_start(&n->crypto_rx, net, n))) {
|
||||
pr_warn("Failed to start crypto RX(%s)!\n", n->peer_id_string);
|
||||
kfree(n);
|
||||
n = NULL;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
n->addr = addr;
|
||||
n->preliminary = preliminary;
|
||||
memcpy(&n->peer_id, peer_id, 16);
|
||||
n->net = net;
|
||||
n->peer_net = NULL;
|
||||
@ -463,22 +538,14 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
|
||||
n->signature = INVALID_NODE_SIG;
|
||||
n->active_links[0] = INVALID_BEARER_ID;
|
||||
n->active_links[1] = INVALID_BEARER_ID;
|
||||
if (!tipc_link_bc_create(net, tipc_own_addr(net),
|
||||
addr, U16_MAX,
|
||||
tipc_link_window(tipc_bc_sndlink(net)),
|
||||
n->capabilities,
|
||||
&n->bc_entry.inputq1,
|
||||
&n->bc_entry.namedq,
|
||||
tipc_bc_sndlink(net),
|
||||
&n->bc_entry.link)) {
|
||||
pr_warn("Broadcast rcv link creation failed, no memory\n");
|
||||
kfree(n);
|
||||
n = NULL;
|
||||
goto exit;
|
||||
}
|
||||
n->bc_entry.link = NULL;
|
||||
tipc_node_get(n);
|
||||
timer_setup(&n->timer, tipc_node_timeout, 0);
|
||||
n->keepalive_intv = U32_MAX;
|
||||
/* Start a slow timer anyway, crypto needs it */
|
||||
n->keepalive_intv = 10000;
|
||||
intv = jiffies + msecs_to_jiffies(n->keepalive_intv);
|
||||
if (!mod_timer(&n->timer, intv))
|
||||
tipc_node_get(n);
|
||||
hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]);
|
||||
list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
|
||||
if (n->addr < temp_node->addr)
|
||||
@ -696,6 +763,10 @@ static void tipc_node_timeout(struct timer_list *t)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
/* Take any crypto key related actions first */
|
||||
tipc_crypto_timeout(n->crypto_rx);
|
||||
#endif
|
||||
__skb_queue_head_init(&xmitq);
|
||||
|
||||
/* Initial node interval to value larger (10 seconds), then it will be
|
||||
@ -716,7 +787,7 @@ static void tipc_node_timeout(struct timer_list *t)
|
||||
remains--;
|
||||
}
|
||||
tipc_node_read_unlock(n);
|
||||
tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr);
|
||||
tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr, n);
|
||||
if (rc & TIPC_LINK_DOWN_EVT)
|
||||
tipc_node_link_down(n, bearer_id, false);
|
||||
}
|
||||
@ -748,7 +819,7 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id,
|
||||
n->link_id = tipc_link_id(nl);
|
||||
|
||||
/* Leave room for tunnel header when returning 'mtu' to users: */
|
||||
n->links[bearer_id].mtu = tipc_link_mtu(nl) - INT_H_SIZE;
|
||||
n->links[bearer_id].mtu = tipc_link_mss(nl);
|
||||
|
||||
tipc_bearer_add_dest(n->net, bearer_id, n->addr);
|
||||
tipc_bcast_inc_bearer_dst_cnt(n->net, bearer_id);
|
||||
@ -802,7 +873,7 @@ static void tipc_node_link_up(struct tipc_node *n, int bearer_id,
|
||||
tipc_node_write_lock(n);
|
||||
__tipc_node_link_up(n, bearer_id, xmitq);
|
||||
maddr = &n->links[bearer_id].maddr;
|
||||
tipc_bearer_xmit(n->net, bearer_id, xmitq, maddr);
|
||||
tipc_bearer_xmit(n->net, bearer_id, xmitq, maddr, n);
|
||||
tipc_node_write_unlock(n);
|
||||
}
|
||||
|
||||
@ -957,7 +1028,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
|
||||
if (delete)
|
||||
tipc_mon_remove_peer(n->net, n->addr, old_bearer_id);
|
||||
if (!skb_queue_empty(&xmitq))
|
||||
tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
|
||||
tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr, n);
|
||||
tipc_sk_rcv(n->net, &le->inputq);
|
||||
}
|
||||
|
||||
@ -1001,6 +1072,8 @@ u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr)
|
||||
{
|
||||
struct tipc_net *tn = tipc_net(net);
|
||||
struct tipc_node *n;
|
||||
bool preliminary;
|
||||
u32 sugg_addr;
|
||||
|
||||
/* Suggest new address if some other peer is using this one */
|
||||
n = tipc_node_find(net, addr);
|
||||
@ -1016,9 +1089,11 @@ u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr)
|
||||
/* Suggest previously used address if peer is known */
|
||||
n = tipc_node_find_by_id(net, id);
|
||||
if (n) {
|
||||
addr = n->addr;
|
||||
sugg_addr = n->addr;
|
||||
preliminary = n->preliminary;
|
||||
tipc_node_put(n);
|
||||
return addr;
|
||||
if (!preliminary)
|
||||
return sugg_addr;
|
||||
}
|
||||
|
||||
/* Even this node may be in conflict */
|
||||
@ -1035,7 +1110,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
|
||||
bool *respond, bool *dupl_addr)
|
||||
{
|
||||
struct tipc_node *n;
|
||||
struct tipc_link *l;
|
||||
struct tipc_link *l, *snd_l;
|
||||
struct tipc_link_entry *le;
|
||||
bool addr_match = false;
|
||||
bool sign_match = false;
|
||||
@ -1049,12 +1124,27 @@ void tipc_node_check_dest(struct net *net, u32 addr,
|
||||
*dupl_addr = false;
|
||||
*respond = false;
|
||||
|
||||
n = tipc_node_create(net, addr, peer_id, capabilities, signature,
|
||||
hash_mixes);
|
||||
n = tipc_node_create(net, addr, peer_id, capabilities, hash_mixes,
|
||||
false);
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
tipc_node_write_lock(n);
|
||||
if (unlikely(!n->bc_entry.link)) {
|
||||
snd_l = tipc_bc_sndlink(net);
|
||||
if (!tipc_link_bc_create(net, tipc_own_addr(net),
|
||||
addr, U16_MAX,
|
||||
tipc_link_window(snd_l),
|
||||
n->capabilities,
|
||||
&n->bc_entry.inputq1,
|
||||
&n->bc_entry.namedq, snd_l,
|
||||
&n->bc_entry.link)) {
|
||||
pr_warn("Broadcast rcv link creation failed, no mem\n");
|
||||
tipc_node_write_unlock_fast(n);
|
||||
tipc_node_put(n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
le = &n->links[b->identity];
|
||||
|
||||
@ -1592,7 +1682,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list,
|
||||
if (unlikely(rc == -ENOBUFS))
|
||||
tipc_node_link_down(n, bearer_id, false);
|
||||
else
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr);
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr, n);
|
||||
|
||||
tipc_node_put(n);
|
||||
|
||||
@ -1740,7 +1830,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id
|
||||
}
|
||||
|
||||
if (!skb_queue_empty(&xmitq))
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr);
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr, n);
|
||||
|
||||
if (!skb_queue_empty(&be->inputq1))
|
||||
tipc_node_mcast_rcv(n);
|
||||
@ -1918,20 +2008,38 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
|
||||
void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
|
||||
{
|
||||
struct sk_buff_head xmitq;
|
||||
struct tipc_node *n;
|
||||
struct tipc_msg *hdr;
|
||||
int bearer_id = b->identity;
|
||||
struct tipc_link_entry *le;
|
||||
struct tipc_msg *hdr;
|
||||
struct tipc_node *n;
|
||||
int bearer_id = b->identity;
|
||||
u32 self = tipc_own_addr(net);
|
||||
int usr, rc = 0;
|
||||
u16 bc_ack;
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
struct tipc_ehdr *ehdr;
|
||||
|
||||
__skb_queue_head_init(&xmitq);
|
||||
/* Check if message must be decrypted first */
|
||||
if (TIPC_SKB_CB(skb)->decrypted || !tipc_ehdr_validate(skb))
|
||||
goto rcv;
|
||||
|
||||
ehdr = (struct tipc_ehdr *)skb->data;
|
||||
if (likely(ehdr->user != LINK_CONFIG)) {
|
||||
n = tipc_node_find(net, ntohl(ehdr->addr));
|
||||
if (unlikely(!n))
|
||||
goto discard;
|
||||
} else {
|
||||
n = tipc_node_find_by_id(net, ehdr->id);
|
||||
}
|
||||
tipc_crypto_rcv(net, (n) ? n->crypto_rx : NULL, &skb, b);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
rcv:
|
||||
#endif
|
||||
/* Ensure message is well-formed before touching the header */
|
||||
TIPC_SKB_CB(skb)->validated = false;
|
||||
if (unlikely(!tipc_msg_validate(&skb)))
|
||||
goto discard;
|
||||
__skb_queue_head_init(&xmitq);
|
||||
hdr = buf_msg(skb);
|
||||
usr = msg_user(hdr);
|
||||
bc_ack = msg_bcast_ack(hdr);
|
||||
@ -2002,7 +2110,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
|
||||
tipc_sk_rcv(net, &le->inputq);
|
||||
|
||||
if (!skb_queue_empty(&xmitq))
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr);
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr, n);
|
||||
|
||||
tipc_node_put(n);
|
||||
discard:
|
||||
@ -2033,7 +2141,7 @@ void tipc_node_apply_property(struct net *net, struct tipc_bearer *b,
|
||||
tipc_link_set_mtu(e->link, b->mtu);
|
||||
}
|
||||
tipc_node_write_unlock(n);
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &e->maddr);
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &e->maddr, NULL);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
@ -2134,6 +2242,8 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
}
|
||||
|
||||
list_for_each_entry_rcu(node, &tn->node_list, list) {
|
||||
if (node->preliminary)
|
||||
continue;
|
||||
if (last_addr) {
|
||||
if (node->addr == last_addr)
|
||||
last_addr = 0;
|
||||
@ -2273,7 +2383,8 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
out:
|
||||
tipc_node_read_unlock(node);
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr);
|
||||
tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr,
|
||||
NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -2649,11 +2760,141 @@ int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
u32 tipc_node_get_addr(struct tipc_node *node)
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
static int tipc_nl_retrieve_key(struct nlattr **attrs,
|
||||
struct tipc_aead_key **key)
|
||||
{
|
||||
return (node) ? node->addr : 0;
|
||||
struct nlattr *attr = attrs[TIPC_NLA_NODE_KEY];
|
||||
|
||||
if (!attr)
|
||||
return -ENODATA;
|
||||
|
||||
*key = (struct tipc_aead_key *)nla_data(attr);
|
||||
if (nla_len(attr) < tipc_aead_key_size(*key))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tipc_nl_retrieve_nodeid(struct nlattr **attrs, u8 **node_id)
|
||||
{
|
||||
struct nlattr *attr = attrs[TIPC_NLA_NODE_ID];
|
||||
|
||||
if (!attr)
|
||||
return -ENODATA;
|
||||
|
||||
if (nla_len(attr) < TIPC_NODEID_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
*node_id = (u8 *)nla_data(attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1];
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct tipc_net *tn = tipc_net(net);
|
||||
struct tipc_node *n = NULL;
|
||||
struct tipc_aead_key *ukey;
|
||||
struct tipc_crypto *c;
|
||||
u8 *id, *own_id;
|
||||
int rc = 0;
|
||||
|
||||
if (!info->attrs[TIPC_NLA_NODE])
|
||||
return -EINVAL;
|
||||
|
||||
rc = nla_parse_nested(attrs, TIPC_NLA_NODE_MAX,
|
||||
info->attrs[TIPC_NLA_NODE],
|
||||
tipc_nl_node_policy, info->extack);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
own_id = tipc_own_id(net);
|
||||
if (!own_id) {
|
||||
rc = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = tipc_nl_retrieve_key(attrs, &ukey);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
rc = tipc_aead_key_validate(ukey);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
rc = tipc_nl_retrieve_nodeid(attrs, &id);
|
||||
switch (rc) {
|
||||
case -ENODATA:
|
||||
/* Cluster key mode */
|
||||
rc = tipc_crypto_key_init(tn->crypto_tx, ukey, CLUSTER_KEY);
|
||||
break;
|
||||
case 0:
|
||||
/* Per-node key mode */
|
||||
if (!memcmp(id, own_id, NODE_ID_LEN)) {
|
||||
c = tn->crypto_tx;
|
||||
} else {
|
||||
n = tipc_node_find_by_id(net, id) ?:
|
||||
tipc_node_create(net, 0, id, 0xffffu, 0, true);
|
||||
if (unlikely(!n)) {
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
c = n->crypto_rx;
|
||||
}
|
||||
|
||||
rc = tipc_crypto_key_init(c, ukey, PER_NODE_KEY);
|
||||
if (n)
|
||||
tipc_node_put(n);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return (rc < 0) ? rc : 0;
|
||||
}
|
||||
|
||||
int tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
rtnl_lock();
|
||||
err = __tipc_nl_node_set_key(skb, info);
|
||||
rtnl_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int __tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct tipc_net *tn = tipc_net(net);
|
||||
struct tipc_node *n;
|
||||
|
||||
tipc_crypto_key_flush(tn->crypto_tx);
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(n, &tn->node_list, list)
|
||||
tipc_crypto_key_flush(n->crypto_rx);
|
||||
rcu_read_unlock();
|
||||
|
||||
pr_info("All keys are flushed!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
rtnl_lock();
|
||||
err = __tipc_nl_node_flush_key(skb, info);
|
||||
rtnl_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tipc_node_dump - dump TIPC node data
|
||||
* @n: tipc node to be dumped
|
||||
|
@ -75,6 +75,15 @@ enum {
|
||||
void tipc_node_stop(struct net *net);
|
||||
bool tipc_node_get_id(struct net *net, u32 addr, u8 *id);
|
||||
u32 tipc_node_get_addr(struct tipc_node *node);
|
||||
char *tipc_node_get_id_str(struct tipc_node *node);
|
||||
void tipc_node_put(struct tipc_node *node);
|
||||
struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
|
||||
u16 capabilities, u32 hash_mixes,
|
||||
bool preliminary);
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
struct tipc_crypto *tipc_node_crypto_rx(struct tipc_node *__n);
|
||||
struct tipc_crypto *tipc_node_crypto_rx_by_list(struct list_head *pos);
|
||||
#endif
|
||||
u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr);
|
||||
void tipc_node_check_dest(struct net *net, u32 onode, u8 *peer_id128,
|
||||
struct tipc_bearer *bearer,
|
||||
@ -110,5 +119,9 @@ int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info);
|
||||
int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb);
|
||||
int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
|
||||
struct netlink_callback *cb);
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
int tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info);
|
||||
int tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info);
|
||||
#endif
|
||||
void tipc_node_pre_cleanup_net(struct net *exit_net);
|
||||
#endif
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include "core.h"
|
||||
#include "trace.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
@ -64,6 +65,16 @@ static struct ctl_table tipc_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_doulongvec_minmax,
|
||||
},
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
{
|
||||
.procname = "max_tfms",
|
||||
.data = &sysctl_tipc_max_tfms,
|
||||
.maxlen = sizeof(sysctl_tipc_max_tfms),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = SYSCTL_ONE,
|
||||
},
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -372,6 +372,7 @@ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb)
|
||||
goto out;
|
||||
|
||||
if (b && test_bit(0, &b->up)) {
|
||||
TIPC_SKB_CB(skb)->flags = 0;
|
||||
tipc_rcv(sock_net(sk), skb, b);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user