cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

smc_clc.c (33071B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  Shared Memory Communications over RDMA (SMC-R) and RoCE
      4 *
      5 *  CLC (connection layer control) handshake over initial TCP socket to
      6 *  prepare for RDMA traffic
      7 *
      8 *  Copyright IBM Corp. 2016, 2018
      9 *
     10 *  Author(s):  Ursula Braun <ubraun@linux.vnet.ibm.com>
     11 */
     12
     13#include <linux/in.h>
     14#include <linux/inetdevice.h>
     15#include <linux/if_ether.h>
     16#include <linux/sched/signal.h>
     17#include <linux/utsname.h>
     18#include <linux/ctype.h>
     19
     20#include <net/addrconf.h>
     21#include <net/sock.h>
     22#include <net/tcp.h>
     23
     24#include "smc.h"
     25#include "smc_core.h"
     26#include "smc_clc.h"
     27#include "smc_ib.h"
     28#include "smc_ism.h"
     29#include "smc_netlink.h"
     30
     31#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
     32#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
     33#define SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 78
     34#define SMCR_CLC_ACCEPT_CONFIRM_LEN_V2 108
     35#define SMC_CLC_RECV_BUF_LEN	100
     36
     37/* eye catcher "SMCR" EBCDIC for CLC messages */
     38static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
     39/* eye catcher "SMCD" EBCDIC for CLC messages */
     40static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
     41
     42static u8 smc_hostname[SMC_MAX_HOSTNAME_LEN];
     43
     44struct smc_clc_eid_table {
     45	rwlock_t lock;
     46	struct list_head list;
     47	u8 ueid_cnt;
     48	u8 seid_enabled;
     49};
     50
     51static struct smc_clc_eid_table smc_clc_eid_table;
     52
     53struct smc_clc_eid_entry {
     54	struct list_head list;
     55	u8 eid[SMC_MAX_EID_LEN];
     56};
     57
     58/* The size of a user EID is 32 characters.
     59 * Valid characters should be (single-byte character set) A-Z, 0-9, '.' and '-'.
     60 * Blanks should only be used to pad to the expected size.
     61 * First character must be alphanumeric.
     62 */
     63static bool smc_clc_ueid_valid(char *ueid)
     64{
     65	char *end = ueid + SMC_MAX_EID_LEN;
     66
     67	while (--end >= ueid && isspace(*end))
     68		;
     69	if (end < ueid)
     70		return false;
     71	if (!isalnum(*ueid) || islower(*ueid))
     72		return false;
     73	while (ueid <= end) {
     74		if ((!isalnum(*ueid) || islower(*ueid)) && *ueid != '.' &&
     75		    *ueid != '-')
     76			return false;
     77		ueid++;
     78	}
     79	return true;
     80}
     81
     82static int smc_clc_ueid_add(char *ueid)
     83{
     84	struct smc_clc_eid_entry *new_ueid, *tmp_ueid;
     85	int rc;
     86
     87	if (!smc_clc_ueid_valid(ueid))
     88		return -EINVAL;
     89
     90	/* add a new ueid entry to the ueid table if there isn't one */
     91	new_ueid = kzalloc(sizeof(*new_ueid), GFP_KERNEL);
     92	if (!new_ueid)
     93		return -ENOMEM;
     94	memcpy(new_ueid->eid, ueid, SMC_MAX_EID_LEN);
     95
     96	write_lock(&smc_clc_eid_table.lock);
     97	if (smc_clc_eid_table.ueid_cnt >= SMC_MAX_UEID) {
     98		rc = -ERANGE;
     99		goto err_out;
    100	}
    101	list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) {
    102		if (!memcmp(tmp_ueid->eid, ueid, SMC_MAX_EID_LEN)) {
    103			rc = -EEXIST;
    104			goto err_out;
    105		}
    106	}
    107	list_add_tail(&new_ueid->list, &smc_clc_eid_table.list);
    108	smc_clc_eid_table.ueid_cnt++;
    109	write_unlock(&smc_clc_eid_table.lock);
    110	return 0;
    111
    112err_out:
    113	write_unlock(&smc_clc_eid_table.lock);
    114	kfree(new_ueid);
    115	return rc;
    116}
    117
    118int smc_clc_ueid_count(void)
    119{
    120	int count;
    121
    122	read_lock(&smc_clc_eid_table.lock);
    123	count = smc_clc_eid_table.ueid_cnt;
    124	read_unlock(&smc_clc_eid_table.lock);
    125
    126	return count;
    127}
    128
    129int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info)
    130{
    131	struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY];
    132	char *ueid;
    133
    134	if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1)
    135		return -EINVAL;
    136	ueid = (char *)nla_data(nla_ueid);
    137
    138	return smc_clc_ueid_add(ueid);
    139}
    140
    141/* remove one or all ueid entries from the table */
    142static int smc_clc_ueid_remove(char *ueid)
    143{
    144	struct smc_clc_eid_entry *lst_ueid, *tmp_ueid;
    145	int rc = -ENOENT;
    146
    147	/* remove table entry */
    148	write_lock(&smc_clc_eid_table.lock);
    149	list_for_each_entry_safe(lst_ueid, tmp_ueid, &smc_clc_eid_table.list,
    150				 list) {
    151		if (!ueid || !memcmp(lst_ueid->eid, ueid, SMC_MAX_EID_LEN)) {
    152			list_del(&lst_ueid->list);
    153			smc_clc_eid_table.ueid_cnt--;
    154			kfree(lst_ueid);
    155			rc = 0;
    156		}
    157	}
    158	if (!rc && !smc_clc_eid_table.ueid_cnt) {
    159		smc_clc_eid_table.seid_enabled = 1;
    160		rc = -EAGAIN;	/* indicate success and enabling of seid */
    161	}
    162	write_unlock(&smc_clc_eid_table.lock);
    163	return rc;
    164}
    165
    166int smc_nl_remove_ueid(struct sk_buff *skb, struct genl_info *info)
    167{
    168	struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY];
    169	char *ueid;
    170
    171	if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1)
    172		return -EINVAL;
    173	ueid = (char *)nla_data(nla_ueid);
    174
    175	return smc_clc_ueid_remove(ueid);
    176}
    177
    178int smc_nl_flush_ueid(struct sk_buff *skb, struct genl_info *info)
    179{
    180	smc_clc_ueid_remove(NULL);
    181	return 0;
    182}
    183
    184static int smc_nl_ueid_dumpinfo(struct sk_buff *skb, u32 portid, u32 seq,
    185				u32 flags, char *ueid)
    186{
    187	char ueid_str[SMC_MAX_EID_LEN + 1];
    188	void *hdr;
    189
    190	hdr = genlmsg_put(skb, portid, seq, &smc_gen_nl_family,
    191			  flags, SMC_NETLINK_DUMP_UEID);
    192	if (!hdr)
    193		return -ENOMEM;
    194	memcpy(ueid_str, ueid, SMC_MAX_EID_LEN);
    195	ueid_str[SMC_MAX_EID_LEN] = 0;
    196	if (nla_put_string(skb, SMC_NLA_EID_TABLE_ENTRY, ueid_str)) {
    197		genlmsg_cancel(skb, hdr);
    198		return -EMSGSIZE;
    199	}
    200	genlmsg_end(skb, hdr);
    201	return 0;
    202}
    203
    204static int _smc_nl_ueid_dump(struct sk_buff *skb, u32 portid, u32 seq,
    205			     int start_idx)
    206{
    207	struct smc_clc_eid_entry *lst_ueid;
    208	int idx = 0;
    209
    210	read_lock(&smc_clc_eid_table.lock);
    211	list_for_each_entry(lst_ueid, &smc_clc_eid_table.list, list) {
    212		if (idx++ < start_idx)
    213			continue;
    214		if (smc_nl_ueid_dumpinfo(skb, portid, seq, NLM_F_MULTI,
    215					 lst_ueid->eid)) {
    216			--idx;
    217			break;
    218		}
    219	}
    220	read_unlock(&smc_clc_eid_table.lock);
    221	return idx;
    222}
    223
    224int smc_nl_dump_ueid(struct sk_buff *skb, struct netlink_callback *cb)
    225{
    226	struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
    227	int idx;
    228
    229	idx = _smc_nl_ueid_dump(skb, NETLINK_CB(cb->skb).portid,
    230				cb->nlh->nlmsg_seq, cb_ctx->pos[0]);
    231
    232	cb_ctx->pos[0] = idx;
    233	return skb->len;
    234}
    235
    236int smc_nl_dump_seid(struct sk_buff *skb, struct netlink_callback *cb)
    237{
    238	struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
    239	char seid_str[SMC_MAX_EID_LEN + 1];
    240	u8 seid_enabled;
    241	void *hdr;
    242	u8 *seid;
    243
    244	if (cb_ctx->pos[0])
    245		return skb->len;
    246
    247	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
    248			  &smc_gen_nl_family, NLM_F_MULTI,
    249			  SMC_NETLINK_DUMP_SEID);
    250	if (!hdr)
    251		return -ENOMEM;
    252	if (!smc_ism_is_v2_capable())
    253		goto end;
    254
    255	smc_ism_get_system_eid(&seid);
    256	memcpy(seid_str, seid, SMC_MAX_EID_LEN);
    257	seid_str[SMC_MAX_EID_LEN] = 0;
    258	if (nla_put_string(skb, SMC_NLA_SEID_ENTRY, seid_str))
    259		goto err;
    260	read_lock(&smc_clc_eid_table.lock);
    261	seid_enabled = smc_clc_eid_table.seid_enabled;
    262	read_unlock(&smc_clc_eid_table.lock);
    263	if (nla_put_u8(skb, SMC_NLA_SEID_ENABLED, seid_enabled))
    264		goto err;
    265end:
    266	genlmsg_end(skb, hdr);
    267	cb_ctx->pos[0]++;
    268	return skb->len;
    269err:
    270	genlmsg_cancel(skb, hdr);
    271	return -EMSGSIZE;
    272}
    273
    274int smc_nl_enable_seid(struct sk_buff *skb, struct genl_info *info)
    275{
    276	write_lock(&smc_clc_eid_table.lock);
    277	smc_clc_eid_table.seid_enabled = 1;
    278	write_unlock(&smc_clc_eid_table.lock);
    279	return 0;
    280}
    281
    282int smc_nl_disable_seid(struct sk_buff *skb, struct genl_info *info)
    283{
    284	int rc = 0;
    285
    286	write_lock(&smc_clc_eid_table.lock);
    287	if (!smc_clc_eid_table.ueid_cnt)
    288		rc = -ENOENT;
    289	else
    290		smc_clc_eid_table.seid_enabled = 0;
    291	write_unlock(&smc_clc_eid_table.lock);
    292	return rc;
    293}
    294
    295static bool _smc_clc_match_ueid(u8 *peer_ueid)
    296{
    297	struct smc_clc_eid_entry *tmp_ueid;
    298
    299	list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) {
    300		if (!memcmp(tmp_ueid->eid, peer_ueid, SMC_MAX_EID_LEN))
    301			return true;
    302	}
    303	return false;
    304}
    305
    306bool smc_clc_match_eid(u8 *negotiated_eid,
    307		       struct smc_clc_v2_extension *smc_v2_ext,
    308		       u8 *peer_eid, u8 *local_eid)
    309{
    310	bool match = false;
    311	int i;
    312
    313	negotiated_eid[0] = 0;
    314	read_lock(&smc_clc_eid_table.lock);
    315	if (peer_eid && local_eid &&
    316	    smc_clc_eid_table.seid_enabled &&
    317	    smc_v2_ext->hdr.flag.seid &&
    318	    !memcmp(peer_eid, local_eid, SMC_MAX_EID_LEN)) {
    319		memcpy(negotiated_eid, peer_eid, SMC_MAX_EID_LEN);
    320		match = true;
    321		goto out;
    322	}
    323
    324	for (i = 0; i < smc_v2_ext->hdr.eid_cnt; i++) {
    325		if (_smc_clc_match_ueid(smc_v2_ext->user_eids[i])) {
    326			memcpy(negotiated_eid, smc_v2_ext->user_eids[i],
    327			       SMC_MAX_EID_LEN);
    328			match = true;
    329			goto out;
    330		}
    331	}
    332out:
    333	read_unlock(&smc_clc_eid_table.lock);
    334	return match;
    335}
    336
    337/* check arriving CLC proposal */
    338static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)
    339{
    340	struct smc_clc_msg_proposal_prefix *pclc_prfx;
    341	struct smc_clc_smcd_v2_extension *smcd_v2_ext;
    342	struct smc_clc_msg_hdr *hdr = &pclc->hdr;
    343	struct smc_clc_v2_extension *v2_ext;
    344
    345	v2_ext = smc_get_clc_v2_ext(pclc);
    346	pclc_prfx = smc_clc_proposal_get_prefix(pclc);
    347	if (hdr->version == SMC_V1) {
    348		if (hdr->typev1 == SMC_TYPE_N)
    349			return false;
    350		if (ntohs(hdr->length) !=
    351			sizeof(*pclc) + ntohs(pclc->iparea_offset) +
    352			sizeof(*pclc_prfx) +
    353			pclc_prfx->ipv6_prefixes_cnt *
    354				sizeof(struct smc_clc_ipv6_prefix) +
    355			sizeof(struct smc_clc_msg_trail))
    356			return false;
    357	} else {
    358		if (ntohs(hdr->length) !=
    359			sizeof(*pclc) +
    360			sizeof(struct smc_clc_msg_smcd) +
    361			(hdr->typev1 != SMC_TYPE_N ?
    362				sizeof(*pclc_prfx) +
    363				pclc_prfx->ipv6_prefixes_cnt *
    364				sizeof(struct smc_clc_ipv6_prefix) : 0) +
    365			(hdr->typev2 != SMC_TYPE_N ?
    366				sizeof(*v2_ext) +
    367				v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN : 0) +
    368			(smcd_indicated(hdr->typev2) ?
    369				sizeof(*smcd_v2_ext) + v2_ext->hdr.ism_gid_cnt *
    370					sizeof(struct smc_clc_smcd_gid_chid) :
    371				0) +
    372			sizeof(struct smc_clc_msg_trail))
    373			return false;
    374	}
    375	return true;
    376}
    377
    378/* check arriving CLC accept or confirm */
    379static bool
    380smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2)
    381{
    382	struct smc_clc_msg_hdr *hdr = &clc_v2->hdr;
    383
    384	if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
    385		return false;
    386	if (hdr->version == SMC_V1) {
    387		if ((hdr->typev1 == SMC_TYPE_R &&
    388		     ntohs(hdr->length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
    389		    (hdr->typev1 == SMC_TYPE_D &&
    390		     ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
    391			return false;
    392	} else {
    393		if (hdr->typev1 == SMC_TYPE_D &&
    394		    ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 &&
    395		    (ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 +
    396				sizeof(struct smc_clc_first_contact_ext)))
    397			return false;
    398		if (hdr->typev1 == SMC_TYPE_R &&
    399		    ntohs(hdr->length) < SMCR_CLC_ACCEPT_CONFIRM_LEN_V2)
    400			return false;
    401	}
    402	return true;
    403}
    404
    405/* check arriving CLC decline */
    406static bool
    407smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc)
    408{
    409	struct smc_clc_msg_hdr *hdr = &dclc->hdr;
    410
    411	if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
    412		return false;
    413	if (hdr->version == SMC_V1) {
    414		if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline))
    415			return false;
    416	} else {
    417		if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline_v2))
    418			return false;
    419	}
    420	return true;
    421}
    422
    423static void smc_clc_fill_fce(struct smc_clc_first_contact_ext *fce, int *len)
    424{
    425	memset(fce, 0, sizeof(*fce));
    426	fce->os_type = SMC_CLC_OS_LINUX;
    427	fce->release = SMC_RELEASE;
    428	memcpy(fce->hostname, smc_hostname, sizeof(smc_hostname));
    429	(*len) += sizeof(*fce);
    430}
    431
    432/* check if received message has a correct header length and contains valid
    433 * heading and trailing eyecatchers
    434 */
    435static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
    436{
    437	struct smc_clc_msg_accept_confirm_v2 *clc_v2;
    438	struct smc_clc_msg_proposal *pclc;
    439	struct smc_clc_msg_decline *dclc;
    440	struct smc_clc_msg_trail *trl;
    441
    442	if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
    443	    memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
    444		return false;
    445	switch (clcm->type) {
    446	case SMC_CLC_PROPOSAL:
    447		pclc = (struct smc_clc_msg_proposal *)clcm;
    448		if (!smc_clc_msg_prop_valid(pclc))
    449			return false;
    450		trl = (struct smc_clc_msg_trail *)
    451			((u8 *)pclc + ntohs(pclc->hdr.length) - sizeof(*trl));
    452		break;
    453	case SMC_CLC_ACCEPT:
    454	case SMC_CLC_CONFIRM:
    455		clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm;
    456		if (!smc_clc_msg_acc_conf_valid(clc_v2))
    457			return false;
    458		trl = (struct smc_clc_msg_trail *)
    459			((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) -
    460							sizeof(*trl));
    461		break;
    462	case SMC_CLC_DECLINE:
    463		dclc = (struct smc_clc_msg_decline *)clcm;
    464		if (!smc_clc_msg_decl_valid(dclc))
    465			return false;
    466		check_trl = false;
    467		break;
    468	default:
    469		return false;
    470	}
    471	if (check_trl &&
    472	    memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
    473	    memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
    474		return false;
    475	return true;
    476}
    477
    478/* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */
    479static int smc_clc_prfx_set4_rcu(struct dst_entry *dst, __be32 ipv4,
    480				 struct smc_clc_msg_proposal_prefix *prop)
    481{
    482	struct in_device *in_dev = __in_dev_get_rcu(dst->dev);
    483	const struct in_ifaddr *ifa;
    484
    485	if (!in_dev)
    486		return -ENODEV;
    487
    488	in_dev_for_each_ifa_rcu(ifa, in_dev) {
    489		if (!inet_ifa_match(ipv4, ifa))
    490			continue;
    491		prop->prefix_len = inet_mask_len(ifa->ifa_mask);
    492		prop->outgoing_subnet = ifa->ifa_address & ifa->ifa_mask;
    493		/* prop->ipv6_prefixes_cnt = 0; already done by memset before */
    494		return 0;
    495	}
    496	return -ENOENT;
    497}
    498
    499/* fill CLC proposal msg with ipv6 prefixes from device */
    500static int smc_clc_prfx_set6_rcu(struct dst_entry *dst,
    501				 struct smc_clc_msg_proposal_prefix *prop,
    502				 struct smc_clc_ipv6_prefix *ipv6_prfx)
    503{
    504#if IS_ENABLED(CONFIG_IPV6)
    505	struct inet6_dev *in6_dev = __in6_dev_get(dst->dev);
    506	struct inet6_ifaddr *ifa;
    507	int cnt = 0;
    508
    509	if (!in6_dev)
    510		return -ENODEV;
    511	/* use a maximum of 8 IPv6 prefixes from device */
    512	list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
    513		if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)
    514			continue;
    515		ipv6_addr_prefix(&ipv6_prfx[cnt].prefix,
    516				 &ifa->addr, ifa->prefix_len);
    517		ipv6_prfx[cnt].prefix_len = ifa->prefix_len;
    518		cnt++;
    519		if (cnt == SMC_CLC_MAX_V6_PREFIX)
    520			break;
    521	}
    522	prop->ipv6_prefixes_cnt = cnt;
    523	if (cnt)
    524		return 0;
    525#endif
    526	return -ENOENT;
    527}
    528
    529/* retrieve and set prefixes in CLC proposal msg */
    530static int smc_clc_prfx_set(struct socket *clcsock,
    531			    struct smc_clc_msg_proposal_prefix *prop,
    532			    struct smc_clc_ipv6_prefix *ipv6_prfx)
    533{
    534	struct dst_entry *dst = sk_dst_get(clcsock->sk);
    535	struct sockaddr_storage addrs;
    536	struct sockaddr_in6 *addr6;
    537	struct sockaddr_in *addr;
    538	int rc = -ENOENT;
    539
    540	if (!dst) {
    541		rc = -ENOTCONN;
    542		goto out;
    543	}
    544	if (!dst->dev) {
    545		rc = -ENODEV;
    546		goto out_rel;
    547	}
    548	/* get address to which the internal TCP socket is bound */
    549	if (kernel_getsockname(clcsock, (struct sockaddr *)&addrs) < 0)
    550		goto out_rel;
    551	/* analyze IP specific data of net_device belonging to TCP socket */
    552	addr6 = (struct sockaddr_in6 *)&addrs;
    553	rcu_read_lock();
    554	if (addrs.ss_family == PF_INET) {
    555		/* IPv4 */
    556		addr = (struct sockaddr_in *)&addrs;
    557		rc = smc_clc_prfx_set4_rcu(dst, addr->sin_addr.s_addr, prop);
    558	} else if (ipv6_addr_v4mapped(&addr6->sin6_addr)) {
    559		/* mapped IPv4 address - peer is IPv4 only */
    560		rc = smc_clc_prfx_set4_rcu(dst, addr6->sin6_addr.s6_addr32[3],
    561					   prop);
    562	} else {
    563		/* IPv6 */
    564		rc = smc_clc_prfx_set6_rcu(dst, prop, ipv6_prfx);
    565	}
    566	rcu_read_unlock();
    567out_rel:
    568	dst_release(dst);
    569out:
    570	return rc;
    571}
    572
    573/* match ipv4 addrs of dev against addr in CLC proposal */
    574static int smc_clc_prfx_match4_rcu(struct net_device *dev,
    575				   struct smc_clc_msg_proposal_prefix *prop)
    576{
    577	struct in_device *in_dev = __in_dev_get_rcu(dev);
    578	const struct in_ifaddr *ifa;
    579
    580	if (!in_dev)
    581		return -ENODEV;
    582	in_dev_for_each_ifa_rcu(ifa, in_dev) {
    583		if (prop->prefix_len == inet_mask_len(ifa->ifa_mask) &&
    584		    inet_ifa_match(prop->outgoing_subnet, ifa))
    585			return 0;
    586	}
    587
    588	return -ENOENT;
    589}
    590
    591/* match ipv6 addrs of dev against addrs in CLC proposal */
    592static int smc_clc_prfx_match6_rcu(struct net_device *dev,
    593				   struct smc_clc_msg_proposal_prefix *prop)
    594{
    595#if IS_ENABLED(CONFIG_IPV6)
    596	struct inet6_dev *in6_dev = __in6_dev_get(dev);
    597	struct smc_clc_ipv6_prefix *ipv6_prfx;
    598	struct inet6_ifaddr *ifa;
    599	int i, max;
    600
    601	if (!in6_dev)
    602		return -ENODEV;
    603	/* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */
    604	ipv6_prfx = (struct smc_clc_ipv6_prefix *)((u8 *)prop + sizeof(*prop));
    605	max = min_t(u8, prop->ipv6_prefixes_cnt, SMC_CLC_MAX_V6_PREFIX);
    606	list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
    607		if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)
    608			continue;
    609		for (i = 0; i < max; i++) {
    610			if (ifa->prefix_len == ipv6_prfx[i].prefix_len &&
    611			    ipv6_prefix_equal(&ifa->addr, &ipv6_prfx[i].prefix,
    612					      ifa->prefix_len))
    613				return 0;
    614		}
    615	}
    616#endif
    617	return -ENOENT;
    618}
    619
    620/* check if proposed prefixes match one of our device prefixes */
    621int smc_clc_prfx_match(struct socket *clcsock,
    622		       struct smc_clc_msg_proposal_prefix *prop)
    623{
    624	struct dst_entry *dst = sk_dst_get(clcsock->sk);
    625	int rc;
    626
    627	if (!dst) {
    628		rc = -ENOTCONN;
    629		goto out;
    630	}
    631	if (!dst->dev) {
    632		rc = -ENODEV;
    633		goto out_rel;
    634	}
    635	rcu_read_lock();
    636	if (!prop->ipv6_prefixes_cnt)
    637		rc = smc_clc_prfx_match4_rcu(dst->dev, prop);
    638	else
    639		rc = smc_clc_prfx_match6_rcu(dst->dev, prop);
    640	rcu_read_unlock();
    641out_rel:
    642	dst_release(dst);
    643out:
    644	return rc;
    645}
    646
    647/* Wait for data on the tcp-socket, analyze received data
    648 * Returns:
    649 * 0 if success and it was not a decline that we received.
    650 * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send.
    651 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
    652 */
    653int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
    654		     u8 expected_type, unsigned long timeout)
    655{
    656	long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo;
    657	struct sock *clc_sk = smc->clcsock->sk;
    658	struct smc_clc_msg_hdr *clcm = buf;
    659	struct msghdr msg = {NULL, 0};
    660	int reason_code = 0;
    661	struct kvec vec = {buf, buflen};
    662	int len, datlen, recvlen;
    663	bool check_trl = true;
    664	int krflags;
    665
    666	/* peek the first few bytes to determine length of data to receive
    667	 * so we don't consume any subsequent CLC message or payload data
    668	 * in the TCP byte stream
    669	 */
    670	/*
    671	 * Caller must make sure that buflen is no less than
    672	 * sizeof(struct smc_clc_msg_hdr)
    673	 */
    674	krflags = MSG_PEEK | MSG_WAITALL;
    675	clc_sk->sk_rcvtimeo = timeout;
    676	iov_iter_kvec(&msg.msg_iter, READ, &vec, 1,
    677			sizeof(struct smc_clc_msg_hdr));
    678	len = sock_recvmsg(smc->clcsock, &msg, krflags);
    679	if (signal_pending(current)) {
    680		reason_code = -EINTR;
    681		clc_sk->sk_err = EINTR;
    682		smc->sk.sk_err = EINTR;
    683		goto out;
    684	}
    685	if (clc_sk->sk_err) {
    686		reason_code = -clc_sk->sk_err;
    687		if (clc_sk->sk_err == EAGAIN &&
    688		    expected_type == SMC_CLC_DECLINE)
    689			clc_sk->sk_err = 0; /* reset for fallback usage */
    690		else
    691			smc->sk.sk_err = clc_sk->sk_err;
    692		goto out;
    693	}
    694	if (!len) { /* peer has performed orderly shutdown */
    695		smc->sk.sk_err = ECONNRESET;
    696		reason_code = -ECONNRESET;
    697		goto out;
    698	}
    699	if (len < 0) {
    700		if (len != -EAGAIN || expected_type != SMC_CLC_DECLINE)
    701			smc->sk.sk_err = -len;
    702		reason_code = len;
    703		goto out;
    704	}
    705	datlen = ntohs(clcm->length);
    706	if ((len < sizeof(struct smc_clc_msg_hdr)) ||
    707	    (clcm->version < SMC_V1) ||
    708	    ((clcm->type != SMC_CLC_DECLINE) &&
    709	     (clcm->type != expected_type))) {
    710		smc->sk.sk_err = EPROTO;
    711		reason_code = -EPROTO;
    712		goto out;
    713	}
    714
    715	/* receive the complete CLC message */
    716	memset(&msg, 0, sizeof(struct msghdr));
    717	if (datlen > buflen) {
    718		check_trl = false;
    719		recvlen = buflen;
    720	} else {
    721		recvlen = datlen;
    722	}
    723	iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);
    724	krflags = MSG_WAITALL;
    725	len = sock_recvmsg(smc->clcsock, &msg, krflags);
    726	if (len < recvlen || !smc_clc_msg_hdr_valid(clcm, check_trl)) {
    727		smc->sk.sk_err = EPROTO;
    728		reason_code = -EPROTO;
    729		goto out;
    730	}
    731	datlen -= len;
    732	while (datlen) {
    733		u8 tmp[SMC_CLC_RECV_BUF_LEN];
    734
    735		vec.iov_base = &tmp;
    736		vec.iov_len = SMC_CLC_RECV_BUF_LEN;
    737		/* receive remaining proposal message */
    738		recvlen = datlen > SMC_CLC_RECV_BUF_LEN ?
    739						SMC_CLC_RECV_BUF_LEN : datlen;
    740		iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);
    741		len = sock_recvmsg(smc->clcsock, &msg, krflags);
    742		datlen -= len;
    743	}
    744	if (clcm->type == SMC_CLC_DECLINE) {
    745		struct smc_clc_msg_decline *dclc;
    746
    747		dclc = (struct smc_clc_msg_decline *)clcm;
    748		reason_code = SMC_CLC_DECL_PEERDECL;
    749		smc->peer_diagnosis = ntohl(dclc->peer_diagnosis);
    750		if (((struct smc_clc_msg_decline *)buf)->hdr.typev2 &
    751						SMC_FIRST_CONTACT_MASK) {
    752			smc->conn.lgr->sync_err = 1;
    753			smc_lgr_terminate_sched(smc->conn.lgr);
    754		}
    755	}
    756
    757out:
    758	clc_sk->sk_rcvtimeo = rcvtimeo;
    759	return reason_code;
    760}
    761
    762/* send CLC DECLINE message across internal TCP socket */
    763int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version)
    764{
    765	struct smc_clc_msg_decline *dclc_v1;
    766	struct smc_clc_msg_decline_v2 dclc;
    767	struct msghdr msg;
    768	int len, send_len;
    769	struct kvec vec;
    770
    771	dclc_v1 = (struct smc_clc_msg_decline *)&dclc;
    772	memset(&dclc, 0, sizeof(dclc));
    773	memcpy(dclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
    774	dclc.hdr.type = SMC_CLC_DECLINE;
    775	dclc.hdr.version = version;
    776	dclc.os_type = version == SMC_V1 ? 0 : SMC_CLC_OS_LINUX;
    777	dclc.hdr.typev2 = (peer_diag_info == SMC_CLC_DECL_SYNCERR) ?
    778						SMC_FIRST_CONTACT_MASK : 0;
    779	if ((!smc_conn_lgr_valid(&smc->conn) || !smc->conn.lgr->is_smcd) &&
    780	    smc_ib_is_valid_local_systemid())
    781		memcpy(dclc.id_for_peer, local_systemid,
    782		       sizeof(local_systemid));
    783	dclc.peer_diagnosis = htonl(peer_diag_info);
    784	if (version == SMC_V1) {
    785		memcpy(dclc_v1->trl.eyecatcher, SMC_EYECATCHER,
    786		       sizeof(SMC_EYECATCHER));
    787		send_len = sizeof(*dclc_v1);
    788	} else {
    789		memcpy(dclc.trl.eyecatcher, SMC_EYECATCHER,
    790		       sizeof(SMC_EYECATCHER));
    791		send_len = sizeof(dclc);
    792	}
    793	dclc.hdr.length = htons(send_len);
    794
    795	memset(&msg, 0, sizeof(msg));
    796	vec.iov_base = &dclc;
    797	vec.iov_len = send_len;
    798	len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, send_len);
    799	if (len < 0 || len < send_len)
    800		len = -EPROTO;
    801	return len > 0 ? 0 : len;
    802}
    803
    804/* send CLC PROPOSAL message across internal TCP socket */
    805int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
    806{
    807	struct smc_clc_smcd_v2_extension *smcd_v2_ext;
    808	struct smc_clc_msg_proposal_prefix *pclc_prfx;
    809	struct smc_clc_msg_proposal *pclc_base;
    810	struct smc_clc_smcd_gid_chid *gidchids;
    811	struct smc_clc_msg_proposal_area *pclc;
    812	struct smc_clc_ipv6_prefix *ipv6_prfx;
    813	struct smc_clc_v2_extension *v2_ext;
    814	struct smc_clc_msg_smcd *pclc_smcd;
    815	struct smc_clc_msg_trail *trl;
    816	int len, i, plen, rc;
    817	int reason_code = 0;
    818	struct kvec vec[8];
    819	struct msghdr msg;
    820
    821	pclc = kzalloc(sizeof(*pclc), GFP_KERNEL);
    822	if (!pclc)
    823		return -ENOMEM;
    824
    825	pclc_base = &pclc->pclc_base;
    826	pclc_smcd = &pclc->pclc_smcd;
    827	pclc_prfx = &pclc->pclc_prfx;
    828	ipv6_prfx = pclc->pclc_prfx_ipv6;
    829	v2_ext = &pclc->pclc_v2_ext;
    830	smcd_v2_ext = &pclc->pclc_smcd_v2_ext;
    831	gidchids = pclc->pclc_gidchids;
    832	trl = &pclc->pclc_trl;
    833
    834	pclc_base->hdr.version = SMC_V2;
    835	pclc_base->hdr.typev1 = ini->smc_type_v1;
    836	pclc_base->hdr.typev2 = ini->smc_type_v2;
    837	plen = sizeof(*pclc_base) + sizeof(*pclc_smcd) + sizeof(*trl);
    838
    839	/* retrieve ip prefixes for CLC proposal msg */
    840	if (ini->smc_type_v1 != SMC_TYPE_N) {
    841		rc = smc_clc_prfx_set(smc->clcsock, pclc_prfx, ipv6_prfx);
    842		if (rc) {
    843			if (ini->smc_type_v2 == SMC_TYPE_N) {
    844				kfree(pclc);
    845				return SMC_CLC_DECL_CNFERR;
    846			}
    847			pclc_base->hdr.typev1 = SMC_TYPE_N;
    848		} else {
    849			pclc_base->iparea_offset = htons(sizeof(*pclc_smcd));
    850			plen += sizeof(*pclc_prfx) +
    851					pclc_prfx->ipv6_prefixes_cnt *
    852					sizeof(ipv6_prfx[0]);
    853		}
    854	}
    855
    856	/* build SMC Proposal CLC message */
    857	memcpy(pclc_base->hdr.eyecatcher, SMC_EYECATCHER,
    858	       sizeof(SMC_EYECATCHER));
    859	pclc_base->hdr.type = SMC_CLC_PROPOSAL;
    860	if (smcr_indicated(ini->smc_type_v1)) {
    861		/* add SMC-R specifics */
    862		memcpy(pclc_base->lcl.id_for_peer, local_systemid,
    863		       sizeof(local_systemid));
    864		memcpy(pclc_base->lcl.gid, ini->ib_gid, SMC_GID_SIZE);
    865		memcpy(pclc_base->lcl.mac, &ini->ib_dev->mac[ini->ib_port - 1],
    866		       ETH_ALEN);
    867	}
    868	if (smcd_indicated(ini->smc_type_v1)) {
    869		/* add SMC-D specifics */
    870		if (ini->ism_dev[0]) {
    871			pclc_smcd->ism.gid = htonll(ini->ism_dev[0]->local_gid);
    872			pclc_smcd->ism.chid =
    873				htons(smc_ism_get_chid(ini->ism_dev[0]));
    874		}
    875	}
    876	if (ini->smc_type_v2 == SMC_TYPE_N) {
    877		pclc_smcd->v2_ext_offset = 0;
    878	} else {
    879		struct smc_clc_eid_entry *ueident;
    880		u16 v2_ext_offset;
    881
    882		v2_ext->hdr.flag.release = SMC_RELEASE;
    883		v2_ext_offset = sizeof(*pclc_smcd) -
    884			offsetofend(struct smc_clc_msg_smcd, v2_ext_offset);
    885		if (ini->smc_type_v1 != SMC_TYPE_N)
    886			v2_ext_offset += sizeof(*pclc_prfx) +
    887						pclc_prfx->ipv6_prefixes_cnt *
    888						sizeof(ipv6_prfx[0]);
    889		pclc_smcd->v2_ext_offset = htons(v2_ext_offset);
    890		plen += sizeof(*v2_ext);
    891
    892		read_lock(&smc_clc_eid_table.lock);
    893		v2_ext->hdr.eid_cnt = smc_clc_eid_table.ueid_cnt;
    894		plen += smc_clc_eid_table.ueid_cnt * SMC_MAX_EID_LEN;
    895		i = 0;
    896		list_for_each_entry(ueident, &smc_clc_eid_table.list, list) {
    897			memcpy(v2_ext->user_eids[i++], ueident->eid,
    898			       sizeof(ueident->eid));
    899		}
    900		read_unlock(&smc_clc_eid_table.lock);
    901	}
    902	if (smcd_indicated(ini->smc_type_v2)) {
    903		u8 *eid = NULL;
    904
    905		v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled;
    906		v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt;
    907		v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) -
    908				offsetofend(struct smc_clnt_opts_area_hdr,
    909					    smcd_v2_ext_offset) +
    910				v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN);
    911		smc_ism_get_system_eid(&eid);
    912		if (eid && v2_ext->hdr.flag.seid)
    913			memcpy(smcd_v2_ext->system_eid, eid, SMC_MAX_EID_LEN);
    914		plen += sizeof(*smcd_v2_ext);
    915		if (ini->ism_offered_cnt) {
    916			for (i = 1; i <= ini->ism_offered_cnt; i++) {
    917				gidchids[i - 1].gid =
    918					htonll(ini->ism_dev[i]->local_gid);
    919				gidchids[i - 1].chid =
    920					htons(smc_ism_get_chid(ini->ism_dev[i]));
    921			}
    922			plen += ini->ism_offered_cnt *
    923				sizeof(struct smc_clc_smcd_gid_chid);
    924		}
    925	}
    926	if (smcr_indicated(ini->smc_type_v2))
    927		memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
    928
    929	pclc_base->hdr.length = htons(plen);
    930	memcpy(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
    931
    932	/* send SMC Proposal CLC message */
    933	memset(&msg, 0, sizeof(msg));
    934	i = 0;
    935	vec[i].iov_base = pclc_base;
    936	vec[i++].iov_len = sizeof(*pclc_base);
    937	vec[i].iov_base = pclc_smcd;
    938	vec[i++].iov_len = sizeof(*pclc_smcd);
    939	if (ini->smc_type_v1 != SMC_TYPE_N) {
    940		vec[i].iov_base = pclc_prfx;
    941		vec[i++].iov_len = sizeof(*pclc_prfx);
    942		if (pclc_prfx->ipv6_prefixes_cnt > 0) {
    943			vec[i].iov_base = ipv6_prfx;
    944			vec[i++].iov_len = pclc_prfx->ipv6_prefixes_cnt *
    945					   sizeof(ipv6_prfx[0]);
    946		}
    947	}
    948	if (ini->smc_type_v2 != SMC_TYPE_N) {
    949		vec[i].iov_base = v2_ext;
    950		vec[i++].iov_len = sizeof(*v2_ext) +
    951				   (v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN);
    952		if (smcd_indicated(ini->smc_type_v2)) {
    953			vec[i].iov_base = smcd_v2_ext;
    954			vec[i++].iov_len = sizeof(*smcd_v2_ext);
    955			if (ini->ism_offered_cnt) {
    956				vec[i].iov_base = gidchids;
    957				vec[i++].iov_len = ini->ism_offered_cnt *
    958					sizeof(struct smc_clc_smcd_gid_chid);
    959			}
    960		}
    961	}
    962	vec[i].iov_base = trl;
    963	vec[i++].iov_len = sizeof(*trl);
    964	/* due to the few bytes needed for clc-handshake this cannot block */
    965	len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
    966	if (len < 0) {
    967		smc->sk.sk_err = smc->clcsock->sk->sk_err;
    968		reason_code = -smc->sk.sk_err;
    969	} else if (len < ntohs(pclc_base->hdr.length)) {
    970		reason_code = -ENETUNREACH;
    971		smc->sk.sk_err = -reason_code;
    972	}
    973
    974	kfree(pclc);
    975	return reason_code;
    976}
    977
    978/* build and send CLC CONFIRM / ACCEPT message */
    979static int smc_clc_send_confirm_accept(struct smc_sock *smc,
    980				       struct smc_clc_msg_accept_confirm_v2 *clc_v2,
    981				       int first_contact, u8 version,
    982				       u8 *eid, struct smc_init_info *ini)
    983{
    984	struct smc_connection *conn = &smc->conn;
    985	struct smc_clc_msg_accept_confirm *clc;
    986	struct smc_clc_first_contact_ext fce;
    987	struct smc_clc_fce_gid_ext gle;
    988	struct smc_clc_msg_trail trl;
    989	struct kvec vec[5];
    990	struct msghdr msg;
    991	int i, len;
    992
    993	/* send SMC Confirm CLC msg */
    994	clc = (struct smc_clc_msg_accept_confirm *)clc_v2;
    995	clc->hdr.version = version;	/* SMC version */
    996	if (first_contact)
    997		clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK;
    998	if (conn->lgr->is_smcd) {
    999		/* SMC-D specific settings */
   1000		memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
   1001		       sizeof(SMCD_EYECATCHER));
   1002		clc->hdr.typev1 = SMC_TYPE_D;
   1003		clc->d0.gid = conn->lgr->smcd->local_gid;
   1004		clc->d0.token = conn->rmb_desc->token;
   1005		clc->d0.dmbe_size = conn->rmbe_size_short;
   1006		clc->d0.dmbe_idx = 0;
   1007		memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
   1008		if (version == SMC_V1) {
   1009			clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
   1010		} else {
   1011			clc_v2->d1.chid =
   1012				htons(smc_ism_get_chid(conn->lgr->smcd));
   1013			if (eid && eid[0])
   1014				memcpy(clc_v2->d1.eid, eid, SMC_MAX_EID_LEN);
   1015			len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2;
   1016			if (first_contact)
   1017				smc_clc_fill_fce(&fce, &len);
   1018			clc_v2->hdr.length = htons(len);
   1019		}
   1020		memcpy(trl.eyecatcher, SMCD_EYECATCHER,
   1021		       sizeof(SMCD_EYECATCHER));
   1022	} else {
   1023		struct smc_link *link = conn->lnk;
   1024
   1025		/* SMC-R specific settings */
   1026		memcpy(clc->hdr.eyecatcher, SMC_EYECATCHER,
   1027		       sizeof(SMC_EYECATCHER));
   1028		clc->hdr.typev1 = SMC_TYPE_R;
   1029		clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
   1030		memcpy(clc->r0.lcl.id_for_peer, local_systemid,
   1031		       sizeof(local_systemid));
   1032		memcpy(&clc->r0.lcl.gid, link->gid, SMC_GID_SIZE);
   1033		memcpy(&clc->r0.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
   1034		       ETH_ALEN);
   1035		hton24(clc->r0.qpn, link->roce_qp->qp_num);
   1036		clc->r0.rmb_rkey =
   1037			htonl(conn->rmb_desc->mr_rx[link->link_idx]->rkey);
   1038		clc->r0.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */
   1039		clc->r0.rmbe_alert_token = htonl(conn->alert_token_local);
   1040		switch (clc->hdr.type) {
   1041		case SMC_CLC_ACCEPT:
   1042			clc->r0.qp_mtu = link->path_mtu;
   1043			break;
   1044		case SMC_CLC_CONFIRM:
   1045			clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu);
   1046			break;
   1047		}
   1048		clc->r0.rmbe_size = conn->rmbe_size_short;
   1049		clc->r0.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address
   1050				(conn->rmb_desc->sgt[link->link_idx].sgl));
   1051		hton24(clc->r0.psn, link->psn_initial);
   1052		if (version == SMC_V1) {
   1053			clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
   1054		} else {
   1055			if (eid && eid[0])
   1056				memcpy(clc_v2->r1.eid, eid, SMC_MAX_EID_LEN);
   1057			len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2;
   1058			if (first_contact) {
   1059				smc_clc_fill_fce(&fce, &len);
   1060				fce.v2_direct = !link->lgr->uses_gateway;
   1061				memset(&gle, 0, sizeof(gle));
   1062				if (ini && clc->hdr.type == SMC_CLC_CONFIRM) {
   1063					gle.gid_cnt = ini->smcrv2.gidlist.len;
   1064					len += sizeof(gle);
   1065					len += gle.gid_cnt * sizeof(gle.gid[0]);
   1066				} else {
   1067					len += sizeof(gle.reserved);
   1068				}
   1069			}
   1070			clc_v2->hdr.length = htons(len);
   1071		}
   1072		memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
   1073	}
   1074
   1075	memset(&msg, 0, sizeof(msg));
   1076	i = 0;
   1077	vec[i].iov_base = clc_v2;
   1078	if (version > SMC_V1)
   1079		vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
   1080					SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 :
   1081					SMCR_CLC_ACCEPT_CONFIRM_LEN_V2) -
   1082				   sizeof(trl);
   1083	else
   1084		vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
   1085						SMCD_CLC_ACCEPT_CONFIRM_LEN :
   1086						SMCR_CLC_ACCEPT_CONFIRM_LEN) -
   1087				   sizeof(trl);
   1088	if (version > SMC_V1 && first_contact) {
   1089		vec[i].iov_base = &fce;
   1090		vec[i++].iov_len = sizeof(fce);
   1091		if (!conn->lgr->is_smcd) {
   1092			if (clc->hdr.type == SMC_CLC_CONFIRM) {
   1093				vec[i].iov_base = &gle;
   1094				vec[i++].iov_len = sizeof(gle);
   1095				vec[i].iov_base = &ini->smcrv2.gidlist.list;
   1096				vec[i++].iov_len = gle.gid_cnt *
   1097						   sizeof(gle.gid[0]);
   1098			} else {
   1099				vec[i].iov_base = &gle.reserved;
   1100				vec[i++].iov_len = sizeof(gle.reserved);
   1101			}
   1102		}
   1103	}
   1104	vec[i].iov_base = &trl;
   1105	vec[i++].iov_len = sizeof(trl);
   1106	return kernel_sendmsg(smc->clcsock, &msg, vec, 1,
   1107			      ntohs(clc->hdr.length));
   1108}
   1109
   1110/* send CLC CONFIRM message across internal TCP socket */
   1111int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
   1112			 u8 version, u8 *eid, struct smc_init_info *ini)
   1113{
   1114	struct smc_clc_msg_accept_confirm_v2 cclc_v2;
   1115	int reason_code = 0;
   1116	int len;
   1117
   1118	/* send SMC Confirm CLC msg */
   1119	memset(&cclc_v2, 0, sizeof(cclc_v2));
   1120	cclc_v2.hdr.type = SMC_CLC_CONFIRM;
   1121	len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact,
   1122					  version, eid, ini);
   1123	if (len < ntohs(cclc_v2.hdr.length)) {
   1124		if (len >= 0) {
   1125			reason_code = -ENETUNREACH;
   1126			smc->sk.sk_err = -reason_code;
   1127		} else {
   1128			smc->sk.sk_err = smc->clcsock->sk->sk_err;
   1129			reason_code = -smc->sk.sk_err;
   1130		}
   1131	}
   1132	return reason_code;
   1133}
   1134
   1135/* send CLC ACCEPT message across internal TCP socket */
   1136int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact,
   1137			u8 version, u8 *negotiated_eid)
   1138{
   1139	struct smc_clc_msg_accept_confirm_v2 aclc_v2;
   1140	int len;
   1141
   1142	memset(&aclc_v2, 0, sizeof(aclc_v2));
   1143	aclc_v2.hdr.type = SMC_CLC_ACCEPT;
   1144	len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact,
   1145					  version, negotiated_eid, NULL);
   1146	if (len < ntohs(aclc_v2.hdr.length))
   1147		len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
   1148
   1149	return len > 0 ? 0 : len;
   1150}
   1151
   1152void smc_clc_get_hostname(u8 **host)
   1153{
   1154	*host = &smc_hostname[0];
   1155}
   1156
   1157void __init smc_clc_init(void)
   1158{
   1159	struct new_utsname *u;
   1160
   1161	memset(smc_hostname, _S, sizeof(smc_hostname)); /* ASCII blanks */
   1162	u = utsname();
   1163	memcpy(smc_hostname, u->nodename,
   1164	       min_t(size_t, strlen(u->nodename), sizeof(smc_hostname)));
   1165
   1166	INIT_LIST_HEAD(&smc_clc_eid_table.list);
   1167	rwlock_init(&smc_clc_eid_table.lock);
   1168	smc_clc_eid_table.ueid_cnt = 0;
   1169	smc_clc_eid_table.seid_enabled = 1;
   1170}
   1171
   1172void smc_clc_exit(void)
   1173{
   1174	smc_clc_ueid_remove(NULL);
   1175}