xref: /kernel/linux/linux-6.6/net/smc/smc_clc.c (revision 62306a36)
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 IS_ENABLED(CONFIG_S390)
159	if (!rc && !smc_clc_eid_table.ueid_cnt) {
160		smc_clc_eid_table.seid_enabled = 1;
161		rc = -EAGAIN;	/* indicate success and enabling of seid */
162	}
163#endif
164	write_unlock(&smc_clc_eid_table.lock);
165	return rc;
166}
167
168int smc_nl_remove_ueid(struct sk_buff *skb, struct genl_info *info)
169{
170	struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY];
171	char *ueid;
172
173	if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1)
174		return -EINVAL;
175	ueid = (char *)nla_data(nla_ueid);
176
177	return smc_clc_ueid_remove(ueid);
178}
179
180int smc_nl_flush_ueid(struct sk_buff *skb, struct genl_info *info)
181{
182	smc_clc_ueid_remove(NULL);
183	return 0;
184}
185
186static int smc_nl_ueid_dumpinfo(struct sk_buff *skb, u32 portid, u32 seq,
187				u32 flags, char *ueid)
188{
189	char ueid_str[SMC_MAX_EID_LEN + 1];
190	void *hdr;
191
192	hdr = genlmsg_put(skb, portid, seq, &smc_gen_nl_family,
193			  flags, SMC_NETLINK_DUMP_UEID);
194	if (!hdr)
195		return -ENOMEM;
196	memcpy(ueid_str, ueid, SMC_MAX_EID_LEN);
197	ueid_str[SMC_MAX_EID_LEN] = 0;
198	if (nla_put_string(skb, SMC_NLA_EID_TABLE_ENTRY, ueid_str)) {
199		genlmsg_cancel(skb, hdr);
200		return -EMSGSIZE;
201	}
202	genlmsg_end(skb, hdr);
203	return 0;
204}
205
206static int _smc_nl_ueid_dump(struct sk_buff *skb, u32 portid, u32 seq,
207			     int start_idx)
208{
209	struct smc_clc_eid_entry *lst_ueid;
210	int idx = 0;
211
212	read_lock(&smc_clc_eid_table.lock);
213	list_for_each_entry(lst_ueid, &smc_clc_eid_table.list, list) {
214		if (idx++ < start_idx)
215			continue;
216		if (smc_nl_ueid_dumpinfo(skb, portid, seq, NLM_F_MULTI,
217					 lst_ueid->eid)) {
218			--idx;
219			break;
220		}
221	}
222	read_unlock(&smc_clc_eid_table.lock);
223	return idx;
224}
225
226int smc_nl_dump_ueid(struct sk_buff *skb, struct netlink_callback *cb)
227{
228	struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
229	int idx;
230
231	idx = _smc_nl_ueid_dump(skb, NETLINK_CB(cb->skb).portid,
232				cb->nlh->nlmsg_seq, cb_ctx->pos[0]);
233
234	cb_ctx->pos[0] = idx;
235	return skb->len;
236}
237
238int smc_nl_dump_seid(struct sk_buff *skb, struct netlink_callback *cb)
239{
240	struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
241	char seid_str[SMC_MAX_EID_LEN + 1];
242	u8 seid_enabled;
243	void *hdr;
244	u8 *seid;
245
246	if (cb_ctx->pos[0])
247		return skb->len;
248
249	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
250			  &smc_gen_nl_family, NLM_F_MULTI,
251			  SMC_NETLINK_DUMP_SEID);
252	if (!hdr)
253		return -ENOMEM;
254	if (!smc_ism_is_v2_capable())
255		goto end;
256
257	smc_ism_get_system_eid(&seid);
258	memcpy(seid_str, seid, SMC_MAX_EID_LEN);
259	seid_str[SMC_MAX_EID_LEN] = 0;
260	if (nla_put_string(skb, SMC_NLA_SEID_ENTRY, seid_str))
261		goto err;
262	read_lock(&smc_clc_eid_table.lock);
263	seid_enabled = smc_clc_eid_table.seid_enabled;
264	read_unlock(&smc_clc_eid_table.lock);
265	if (nla_put_u8(skb, SMC_NLA_SEID_ENABLED, seid_enabled))
266		goto err;
267end:
268	genlmsg_end(skb, hdr);
269	cb_ctx->pos[0]++;
270	return skb->len;
271err:
272	genlmsg_cancel(skb, hdr);
273	return -EMSGSIZE;
274}
275
276int smc_nl_enable_seid(struct sk_buff *skb, struct genl_info *info)
277{
278#if IS_ENABLED(CONFIG_S390)
279	write_lock(&smc_clc_eid_table.lock);
280	smc_clc_eid_table.seid_enabled = 1;
281	write_unlock(&smc_clc_eid_table.lock);
282	return 0;
283#else
284	return -EOPNOTSUPP;
285#endif
286}
287
288int smc_nl_disable_seid(struct sk_buff *skb, struct genl_info *info)
289{
290	int rc = 0;
291
292#if IS_ENABLED(CONFIG_S390)
293	write_lock(&smc_clc_eid_table.lock);
294	if (!smc_clc_eid_table.ueid_cnt)
295		rc = -ENOENT;
296	else
297		smc_clc_eid_table.seid_enabled = 0;
298	write_unlock(&smc_clc_eid_table.lock);
299#else
300	rc = -EOPNOTSUPP;
301#endif
302	return rc;
303}
304
305static bool _smc_clc_match_ueid(u8 *peer_ueid)
306{
307	struct smc_clc_eid_entry *tmp_ueid;
308
309	list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) {
310		if (!memcmp(tmp_ueid->eid, peer_ueid, SMC_MAX_EID_LEN))
311			return true;
312	}
313	return false;
314}
315
316bool smc_clc_match_eid(u8 *negotiated_eid,
317		       struct smc_clc_v2_extension *smc_v2_ext,
318		       u8 *peer_eid, u8 *local_eid)
319{
320	bool match = false;
321	int i;
322
323	negotiated_eid[0] = 0;
324	read_lock(&smc_clc_eid_table.lock);
325	if (peer_eid && local_eid &&
326	    smc_clc_eid_table.seid_enabled &&
327	    smc_v2_ext->hdr.flag.seid &&
328	    !memcmp(peer_eid, local_eid, SMC_MAX_EID_LEN)) {
329		memcpy(negotiated_eid, peer_eid, SMC_MAX_EID_LEN);
330		match = true;
331		goto out;
332	}
333
334	for (i = 0; i < smc_v2_ext->hdr.eid_cnt; i++) {
335		if (_smc_clc_match_ueid(smc_v2_ext->user_eids[i])) {
336			memcpy(negotiated_eid, smc_v2_ext->user_eids[i],
337			       SMC_MAX_EID_LEN);
338			match = true;
339			goto out;
340		}
341	}
342out:
343	read_unlock(&smc_clc_eid_table.lock);
344	return match;
345}
346
347/* check arriving CLC proposal */
348static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)
349{
350	struct smc_clc_msg_proposal_prefix *pclc_prfx;
351	struct smc_clc_smcd_v2_extension *smcd_v2_ext;
352	struct smc_clc_msg_hdr *hdr = &pclc->hdr;
353	struct smc_clc_v2_extension *v2_ext;
354
355	v2_ext = smc_get_clc_v2_ext(pclc);
356	pclc_prfx = smc_clc_proposal_get_prefix(pclc);
357	if (hdr->version == SMC_V1) {
358		if (hdr->typev1 == SMC_TYPE_N)
359			return false;
360		if (ntohs(hdr->length) !=
361			sizeof(*pclc) + ntohs(pclc->iparea_offset) +
362			sizeof(*pclc_prfx) +
363			pclc_prfx->ipv6_prefixes_cnt *
364				sizeof(struct smc_clc_ipv6_prefix) +
365			sizeof(struct smc_clc_msg_trail))
366			return false;
367	} else {
368		if (ntohs(hdr->length) !=
369			sizeof(*pclc) +
370			sizeof(struct smc_clc_msg_smcd) +
371			(hdr->typev1 != SMC_TYPE_N ?
372				sizeof(*pclc_prfx) +
373				pclc_prfx->ipv6_prefixes_cnt *
374				sizeof(struct smc_clc_ipv6_prefix) : 0) +
375			(hdr->typev2 != SMC_TYPE_N ?
376				sizeof(*v2_ext) +
377				v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN : 0) +
378			(smcd_indicated(hdr->typev2) ?
379				sizeof(*smcd_v2_ext) + v2_ext->hdr.ism_gid_cnt *
380					sizeof(struct smc_clc_smcd_gid_chid) :
381				0) +
382			sizeof(struct smc_clc_msg_trail))
383			return false;
384	}
385	return true;
386}
387
388/* check arriving CLC accept or confirm */
389static bool
390smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2)
391{
392	struct smc_clc_msg_hdr *hdr = &clc_v2->hdr;
393
394	if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
395		return false;
396	if (hdr->version == SMC_V1) {
397		if ((hdr->typev1 == SMC_TYPE_R &&
398		     ntohs(hdr->length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
399		    (hdr->typev1 == SMC_TYPE_D &&
400		     ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
401			return false;
402	} else {
403		if (hdr->typev1 == SMC_TYPE_D &&
404		    ntohs(hdr->length) < SMCD_CLC_ACCEPT_CONFIRM_LEN_V2)
405			return false;
406		if (hdr->typev1 == SMC_TYPE_R &&
407		    ntohs(hdr->length) < SMCR_CLC_ACCEPT_CONFIRM_LEN_V2)
408			return false;
409	}
410	return true;
411}
412
413/* check arriving CLC decline */
414static bool
415smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc)
416{
417	struct smc_clc_msg_hdr *hdr = &dclc->hdr;
418
419	if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
420		return false;
421	if (hdr->version == SMC_V1) {
422		if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline))
423			return false;
424	} else {
425		if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline_v2))
426			return false;
427	}
428	return true;
429}
430
431static int smc_clc_fill_fce(struct smc_clc_first_contact_ext_v2x *fce,
432			    struct smc_init_info *ini)
433{
434	int ret = sizeof(*fce);
435
436	memset(fce, 0, sizeof(*fce));
437	fce->fce_v2_base.os_type = SMC_CLC_OS_LINUX;
438	fce->fce_v2_base.release = ini->release_nr;
439	memcpy(fce->fce_v2_base.hostname, smc_hostname, sizeof(smc_hostname));
440	if (ini->is_smcd && ini->release_nr < SMC_RELEASE_1) {
441		ret = sizeof(struct smc_clc_first_contact_ext);
442		goto out;
443	}
444
445	if (ini->release_nr >= SMC_RELEASE_1) {
446		if (!ini->is_smcd) {
447			fce->max_conns = ini->max_conns;
448			fce->max_links = ini->max_links;
449		}
450	}
451
452out:
453	return ret;
454}
455
456/* check if received message has a correct header length and contains valid
457 * heading and trailing eyecatchers
458 */
459static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
460{
461	struct smc_clc_msg_accept_confirm_v2 *clc_v2;
462	struct smc_clc_msg_proposal *pclc;
463	struct smc_clc_msg_decline *dclc;
464	struct smc_clc_msg_trail *trl;
465
466	if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
467	    memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
468		return false;
469	switch (clcm->type) {
470	case SMC_CLC_PROPOSAL:
471		pclc = (struct smc_clc_msg_proposal *)clcm;
472		if (!smc_clc_msg_prop_valid(pclc))
473			return false;
474		trl = (struct smc_clc_msg_trail *)
475			((u8 *)pclc + ntohs(pclc->hdr.length) - sizeof(*trl));
476		break;
477	case SMC_CLC_ACCEPT:
478	case SMC_CLC_CONFIRM:
479		clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm;
480		if (!smc_clc_msg_acc_conf_valid(clc_v2))
481			return false;
482		trl = (struct smc_clc_msg_trail *)
483			((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) -
484							sizeof(*trl));
485		break;
486	case SMC_CLC_DECLINE:
487		dclc = (struct smc_clc_msg_decline *)clcm;
488		if (!smc_clc_msg_decl_valid(dclc))
489			return false;
490		check_trl = false;
491		break;
492	default:
493		return false;
494	}
495	if (check_trl &&
496	    memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
497	    memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
498		return false;
499	return true;
500}
501
502/* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */
503static int smc_clc_prfx_set4_rcu(struct dst_entry *dst, __be32 ipv4,
504				 struct smc_clc_msg_proposal_prefix *prop)
505{
506	struct in_device *in_dev = __in_dev_get_rcu(dst->dev);
507	const struct in_ifaddr *ifa;
508
509	if (!in_dev)
510		return -ENODEV;
511
512	in_dev_for_each_ifa_rcu(ifa, in_dev) {
513		if (!inet_ifa_match(ipv4, ifa))
514			continue;
515		prop->prefix_len = inet_mask_len(ifa->ifa_mask);
516		prop->outgoing_subnet = ifa->ifa_address & ifa->ifa_mask;
517		/* prop->ipv6_prefixes_cnt = 0; already done by memset before */
518		return 0;
519	}
520	return -ENOENT;
521}
522
523/* fill CLC proposal msg with ipv6 prefixes from device */
524static int smc_clc_prfx_set6_rcu(struct dst_entry *dst,
525				 struct smc_clc_msg_proposal_prefix *prop,
526				 struct smc_clc_ipv6_prefix *ipv6_prfx)
527{
528#if IS_ENABLED(CONFIG_IPV6)
529	struct inet6_dev *in6_dev = __in6_dev_get(dst->dev);
530	struct inet6_ifaddr *ifa;
531	int cnt = 0;
532
533	if (!in6_dev)
534		return -ENODEV;
535	/* use a maximum of 8 IPv6 prefixes from device */
536	list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
537		if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)
538			continue;
539		ipv6_addr_prefix(&ipv6_prfx[cnt].prefix,
540				 &ifa->addr, ifa->prefix_len);
541		ipv6_prfx[cnt].prefix_len = ifa->prefix_len;
542		cnt++;
543		if (cnt == SMC_CLC_MAX_V6_PREFIX)
544			break;
545	}
546	prop->ipv6_prefixes_cnt = cnt;
547	if (cnt)
548		return 0;
549#endif
550	return -ENOENT;
551}
552
553/* retrieve and set prefixes in CLC proposal msg */
554static int smc_clc_prfx_set(struct socket *clcsock,
555			    struct smc_clc_msg_proposal_prefix *prop,
556			    struct smc_clc_ipv6_prefix *ipv6_prfx)
557{
558	struct dst_entry *dst = sk_dst_get(clcsock->sk);
559	struct sockaddr_storage addrs;
560	struct sockaddr_in6 *addr6;
561	struct sockaddr_in *addr;
562	int rc = -ENOENT;
563
564	if (!dst) {
565		rc = -ENOTCONN;
566		goto out;
567	}
568	if (!dst->dev) {
569		rc = -ENODEV;
570		goto out_rel;
571	}
572	/* get address to which the internal TCP socket is bound */
573	if (kernel_getsockname(clcsock, (struct sockaddr *)&addrs) < 0)
574		goto out_rel;
575	/* analyze IP specific data of net_device belonging to TCP socket */
576	addr6 = (struct sockaddr_in6 *)&addrs;
577	rcu_read_lock();
578	if (addrs.ss_family == PF_INET) {
579		/* IPv4 */
580		addr = (struct sockaddr_in *)&addrs;
581		rc = smc_clc_prfx_set4_rcu(dst, addr->sin_addr.s_addr, prop);
582	} else if (ipv6_addr_v4mapped(&addr6->sin6_addr)) {
583		/* mapped IPv4 address - peer is IPv4 only */
584		rc = smc_clc_prfx_set4_rcu(dst, addr6->sin6_addr.s6_addr32[3],
585					   prop);
586	} else {
587		/* IPv6 */
588		rc = smc_clc_prfx_set6_rcu(dst, prop, ipv6_prfx);
589	}
590	rcu_read_unlock();
591out_rel:
592	dst_release(dst);
593out:
594	return rc;
595}
596
597/* match ipv4 addrs of dev against addr in CLC proposal */
598static int smc_clc_prfx_match4_rcu(struct net_device *dev,
599				   struct smc_clc_msg_proposal_prefix *prop)
600{
601	struct in_device *in_dev = __in_dev_get_rcu(dev);
602	const struct in_ifaddr *ifa;
603
604	if (!in_dev)
605		return -ENODEV;
606	in_dev_for_each_ifa_rcu(ifa, in_dev) {
607		if (prop->prefix_len == inet_mask_len(ifa->ifa_mask) &&
608		    inet_ifa_match(prop->outgoing_subnet, ifa))
609			return 0;
610	}
611
612	return -ENOENT;
613}
614
615/* match ipv6 addrs of dev against addrs in CLC proposal */
616static int smc_clc_prfx_match6_rcu(struct net_device *dev,
617				   struct smc_clc_msg_proposal_prefix *prop)
618{
619#if IS_ENABLED(CONFIG_IPV6)
620	struct inet6_dev *in6_dev = __in6_dev_get(dev);
621	struct smc_clc_ipv6_prefix *ipv6_prfx;
622	struct inet6_ifaddr *ifa;
623	int i, max;
624
625	if (!in6_dev)
626		return -ENODEV;
627	/* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */
628	ipv6_prfx = (struct smc_clc_ipv6_prefix *)((u8 *)prop + sizeof(*prop));
629	max = min_t(u8, prop->ipv6_prefixes_cnt, SMC_CLC_MAX_V6_PREFIX);
630	list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
631		if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)
632			continue;
633		for (i = 0; i < max; i++) {
634			if (ifa->prefix_len == ipv6_prfx[i].prefix_len &&
635			    ipv6_prefix_equal(&ifa->addr, &ipv6_prfx[i].prefix,
636					      ifa->prefix_len))
637				return 0;
638		}
639	}
640#endif
641	return -ENOENT;
642}
643
644/* check if proposed prefixes match one of our device prefixes */
645int smc_clc_prfx_match(struct socket *clcsock,
646		       struct smc_clc_msg_proposal_prefix *prop)
647{
648	struct dst_entry *dst = sk_dst_get(clcsock->sk);
649	int rc;
650
651	if (!dst) {
652		rc = -ENOTCONN;
653		goto out;
654	}
655	if (!dst->dev) {
656		rc = -ENODEV;
657		goto out_rel;
658	}
659	rcu_read_lock();
660	if (!prop->ipv6_prefixes_cnt)
661		rc = smc_clc_prfx_match4_rcu(dst->dev, prop);
662	else
663		rc = smc_clc_prfx_match6_rcu(dst->dev, prop);
664	rcu_read_unlock();
665out_rel:
666	dst_release(dst);
667out:
668	return rc;
669}
670
671/* Wait for data on the tcp-socket, analyze received data
672 * Returns:
673 * 0 if success and it was not a decline that we received.
674 * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send.
675 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
676 */
677int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
678		     u8 expected_type, unsigned long timeout)
679{
680	long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo;
681	struct sock *clc_sk = smc->clcsock->sk;
682	struct smc_clc_msg_hdr *clcm = buf;
683	struct msghdr msg = {NULL, 0};
684	int reason_code = 0;
685	struct kvec vec = {buf, buflen};
686	int len, datlen, recvlen;
687	bool check_trl = true;
688	int krflags;
689
690	/* peek the first few bytes to determine length of data to receive
691	 * so we don't consume any subsequent CLC message or payload data
692	 * in the TCP byte stream
693	 */
694	/*
695	 * Caller must make sure that buflen is no less than
696	 * sizeof(struct smc_clc_msg_hdr)
697	 */
698	krflags = MSG_PEEK | MSG_WAITALL;
699	clc_sk->sk_rcvtimeo = timeout;
700	iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1,
701			sizeof(struct smc_clc_msg_hdr));
702	len = sock_recvmsg(smc->clcsock, &msg, krflags);
703	if (signal_pending(current)) {
704		reason_code = -EINTR;
705		clc_sk->sk_err = EINTR;
706		smc->sk.sk_err = EINTR;
707		goto out;
708	}
709	if (clc_sk->sk_err) {
710		reason_code = -clc_sk->sk_err;
711		if (clc_sk->sk_err == EAGAIN &&
712		    expected_type == SMC_CLC_DECLINE)
713			clc_sk->sk_err = 0; /* reset for fallback usage */
714		else
715			smc->sk.sk_err = clc_sk->sk_err;
716		goto out;
717	}
718	if (!len) { /* peer has performed orderly shutdown */
719		smc->sk.sk_err = ECONNRESET;
720		reason_code = -ECONNRESET;
721		goto out;
722	}
723	if (len < 0) {
724		if (len != -EAGAIN || expected_type != SMC_CLC_DECLINE)
725			smc->sk.sk_err = -len;
726		reason_code = len;
727		goto out;
728	}
729	datlen = ntohs(clcm->length);
730	if ((len < sizeof(struct smc_clc_msg_hdr)) ||
731	    (clcm->version < SMC_V1) ||
732	    ((clcm->type != SMC_CLC_DECLINE) &&
733	     (clcm->type != expected_type))) {
734		smc->sk.sk_err = EPROTO;
735		reason_code = -EPROTO;
736		goto out;
737	}
738
739	/* receive the complete CLC message */
740	memset(&msg, 0, sizeof(struct msghdr));
741	if (datlen > buflen) {
742		check_trl = false;
743		recvlen = buflen;
744	} else {
745		recvlen = datlen;
746	}
747	iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, recvlen);
748	krflags = MSG_WAITALL;
749	len = sock_recvmsg(smc->clcsock, &msg, krflags);
750	if (len < recvlen || !smc_clc_msg_hdr_valid(clcm, check_trl)) {
751		smc->sk.sk_err = EPROTO;
752		reason_code = -EPROTO;
753		goto out;
754	}
755	datlen -= len;
756	while (datlen) {
757		u8 tmp[SMC_CLC_RECV_BUF_LEN];
758
759		vec.iov_base = &tmp;
760		vec.iov_len = SMC_CLC_RECV_BUF_LEN;
761		/* receive remaining proposal message */
762		recvlen = datlen > SMC_CLC_RECV_BUF_LEN ?
763						SMC_CLC_RECV_BUF_LEN : datlen;
764		iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, recvlen);
765		len = sock_recvmsg(smc->clcsock, &msg, krflags);
766		datlen -= len;
767	}
768	if (clcm->type == SMC_CLC_DECLINE) {
769		struct smc_clc_msg_decline *dclc;
770
771		dclc = (struct smc_clc_msg_decline *)clcm;
772		reason_code = SMC_CLC_DECL_PEERDECL;
773		smc->peer_diagnosis = ntohl(dclc->peer_diagnosis);
774		if (((struct smc_clc_msg_decline *)buf)->hdr.typev2 &
775						SMC_FIRST_CONTACT_MASK) {
776			smc->conn.lgr->sync_err = 1;
777			smc_lgr_terminate_sched(smc->conn.lgr);
778		}
779	}
780
781out:
782	clc_sk->sk_rcvtimeo = rcvtimeo;
783	return reason_code;
784}
785
786/* send CLC DECLINE message across internal TCP socket */
787int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version)
788{
789	struct smc_clc_msg_decline *dclc_v1;
790	struct smc_clc_msg_decline_v2 dclc;
791	struct msghdr msg;
792	int len, send_len;
793	struct kvec vec;
794
795	dclc_v1 = (struct smc_clc_msg_decline *)&dclc;
796	memset(&dclc, 0, sizeof(dclc));
797	memcpy(dclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
798	dclc.hdr.type = SMC_CLC_DECLINE;
799	dclc.hdr.version = version;
800	dclc.os_type = version == SMC_V1 ? 0 : SMC_CLC_OS_LINUX;
801	dclc.hdr.typev2 = (peer_diag_info == SMC_CLC_DECL_SYNCERR) ?
802						SMC_FIRST_CONTACT_MASK : 0;
803	if ((!smc_conn_lgr_valid(&smc->conn) || !smc->conn.lgr->is_smcd) &&
804	    smc_ib_is_valid_local_systemid())
805		memcpy(dclc.id_for_peer, local_systemid,
806		       sizeof(local_systemid));
807	dclc.peer_diagnosis = htonl(peer_diag_info);
808	if (version == SMC_V1) {
809		memcpy(dclc_v1->trl.eyecatcher, SMC_EYECATCHER,
810		       sizeof(SMC_EYECATCHER));
811		send_len = sizeof(*dclc_v1);
812	} else {
813		memcpy(dclc.trl.eyecatcher, SMC_EYECATCHER,
814		       sizeof(SMC_EYECATCHER));
815		send_len = sizeof(dclc);
816	}
817	dclc.hdr.length = htons(send_len);
818
819	memset(&msg, 0, sizeof(msg));
820	vec.iov_base = &dclc;
821	vec.iov_len = send_len;
822	len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, send_len);
823	if (len < 0 || len < send_len)
824		len = -EPROTO;
825	return len > 0 ? 0 : len;
826}
827
828/* send CLC PROPOSAL message across internal TCP socket */
829int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
830{
831	struct smc_clc_smcd_v2_extension *smcd_v2_ext;
832	struct smc_clc_msg_proposal_prefix *pclc_prfx;
833	struct smc_clc_msg_proposal *pclc_base;
834	struct smc_clc_smcd_gid_chid *gidchids;
835	struct smc_clc_msg_proposal_area *pclc;
836	struct smc_clc_ipv6_prefix *ipv6_prfx;
837	struct smc_clc_v2_extension *v2_ext;
838	struct smc_clc_msg_smcd *pclc_smcd;
839	struct smc_clc_msg_trail *trl;
840	struct smcd_dev *smcd;
841	int len, i, plen, rc;
842	int reason_code = 0;
843	struct kvec vec[8];
844	struct msghdr msg;
845
846	pclc = kzalloc(sizeof(*pclc), GFP_KERNEL);
847	if (!pclc)
848		return -ENOMEM;
849
850	pclc_base = &pclc->pclc_base;
851	pclc_smcd = &pclc->pclc_smcd;
852	pclc_prfx = &pclc->pclc_prfx;
853	ipv6_prfx = pclc->pclc_prfx_ipv6;
854	v2_ext = &pclc->pclc_v2_ext;
855	smcd_v2_ext = &pclc->pclc_smcd_v2_ext;
856	gidchids = pclc->pclc_gidchids;
857	trl = &pclc->pclc_trl;
858
859	pclc_base->hdr.version = SMC_V2;
860	pclc_base->hdr.typev1 = ini->smc_type_v1;
861	pclc_base->hdr.typev2 = ini->smc_type_v2;
862	plen = sizeof(*pclc_base) + sizeof(*pclc_smcd) + sizeof(*trl);
863
864	/* retrieve ip prefixes for CLC proposal msg */
865	if (ini->smc_type_v1 != SMC_TYPE_N) {
866		rc = smc_clc_prfx_set(smc->clcsock, pclc_prfx, ipv6_prfx);
867		if (rc) {
868			if (ini->smc_type_v2 == SMC_TYPE_N) {
869				kfree(pclc);
870				return SMC_CLC_DECL_CNFERR;
871			}
872			pclc_base->hdr.typev1 = SMC_TYPE_N;
873		} else {
874			pclc_base->iparea_offset = htons(sizeof(*pclc_smcd));
875			plen += sizeof(*pclc_prfx) +
876					pclc_prfx->ipv6_prefixes_cnt *
877					sizeof(ipv6_prfx[0]);
878		}
879	}
880
881	/* build SMC Proposal CLC message */
882	memcpy(pclc_base->hdr.eyecatcher, SMC_EYECATCHER,
883	       sizeof(SMC_EYECATCHER));
884	pclc_base->hdr.type = SMC_CLC_PROPOSAL;
885	if (smcr_indicated(ini->smc_type_v1)) {
886		/* add SMC-R specifics */
887		memcpy(pclc_base->lcl.id_for_peer, local_systemid,
888		       sizeof(local_systemid));
889		memcpy(pclc_base->lcl.gid, ini->ib_gid, SMC_GID_SIZE);
890		memcpy(pclc_base->lcl.mac, &ini->ib_dev->mac[ini->ib_port - 1],
891		       ETH_ALEN);
892	}
893	if (smcd_indicated(ini->smc_type_v1)) {
894		/* add SMC-D specifics */
895		if (ini->ism_dev[0]) {
896			smcd = ini->ism_dev[0];
897			pclc_smcd->ism.gid =
898				htonll(smcd->ops->get_local_gid(smcd));
899			pclc_smcd->ism.chid =
900				htons(smc_ism_get_chid(ini->ism_dev[0]));
901		}
902	}
903	if (ini->smc_type_v2 == SMC_TYPE_N) {
904		pclc_smcd->v2_ext_offset = 0;
905	} else {
906		struct smc_clc_eid_entry *ueident;
907		u16 v2_ext_offset;
908
909		v2_ext->hdr.flag.release = SMC_RELEASE;
910		v2_ext_offset = sizeof(*pclc_smcd) -
911			offsetofend(struct smc_clc_msg_smcd, v2_ext_offset);
912		if (ini->smc_type_v1 != SMC_TYPE_N)
913			v2_ext_offset += sizeof(*pclc_prfx) +
914						pclc_prfx->ipv6_prefixes_cnt *
915						sizeof(ipv6_prfx[0]);
916		pclc_smcd->v2_ext_offset = htons(v2_ext_offset);
917		plen += sizeof(*v2_ext);
918
919		read_lock(&smc_clc_eid_table.lock);
920		v2_ext->hdr.eid_cnt = smc_clc_eid_table.ueid_cnt;
921		plen += smc_clc_eid_table.ueid_cnt * SMC_MAX_EID_LEN;
922		i = 0;
923		list_for_each_entry(ueident, &smc_clc_eid_table.list, list) {
924			memcpy(v2_ext->user_eids[i++], ueident->eid,
925			       sizeof(ueident->eid));
926		}
927		read_unlock(&smc_clc_eid_table.lock);
928	}
929	if (smcd_indicated(ini->smc_type_v2)) {
930		u8 *eid = NULL;
931
932		v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled;
933		v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt;
934		v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) -
935				offsetofend(struct smc_clnt_opts_area_hdr,
936					    smcd_v2_ext_offset) +
937				v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN);
938		smc_ism_get_system_eid(&eid);
939		if (eid && v2_ext->hdr.flag.seid)
940			memcpy(smcd_v2_ext->system_eid, eid, SMC_MAX_EID_LEN);
941		plen += sizeof(*smcd_v2_ext);
942		if (ini->ism_offered_cnt) {
943			for (i = 1; i <= ini->ism_offered_cnt; i++) {
944				smcd = ini->ism_dev[i];
945				gidchids[i - 1].gid =
946					htonll(smcd->ops->get_local_gid(smcd));
947				gidchids[i - 1].chid =
948					htons(smc_ism_get_chid(ini->ism_dev[i]));
949			}
950			plen += ini->ism_offered_cnt *
951				sizeof(struct smc_clc_smcd_gid_chid);
952		}
953	}
954	if (smcr_indicated(ini->smc_type_v2)) {
955		memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
956		v2_ext->max_conns = SMC_CONN_PER_LGR_PREFER;
957		v2_ext->max_links = SMC_LINKS_PER_LGR_MAX_PREFER;
958	}
959
960	pclc_base->hdr.length = htons(plen);
961	memcpy(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
962
963	/* send SMC Proposal CLC message */
964	memset(&msg, 0, sizeof(msg));
965	i = 0;
966	vec[i].iov_base = pclc_base;
967	vec[i++].iov_len = sizeof(*pclc_base);
968	vec[i].iov_base = pclc_smcd;
969	vec[i++].iov_len = sizeof(*pclc_smcd);
970	if (ini->smc_type_v1 != SMC_TYPE_N) {
971		vec[i].iov_base = pclc_prfx;
972		vec[i++].iov_len = sizeof(*pclc_prfx);
973		if (pclc_prfx->ipv6_prefixes_cnt > 0) {
974			vec[i].iov_base = ipv6_prfx;
975			vec[i++].iov_len = pclc_prfx->ipv6_prefixes_cnt *
976					   sizeof(ipv6_prfx[0]);
977		}
978	}
979	if (ini->smc_type_v2 != SMC_TYPE_N) {
980		vec[i].iov_base = v2_ext;
981		vec[i++].iov_len = sizeof(*v2_ext) +
982				   (v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN);
983		if (smcd_indicated(ini->smc_type_v2)) {
984			vec[i].iov_base = smcd_v2_ext;
985			vec[i++].iov_len = sizeof(*smcd_v2_ext);
986			if (ini->ism_offered_cnt) {
987				vec[i].iov_base = gidchids;
988				vec[i++].iov_len = ini->ism_offered_cnt *
989					sizeof(struct smc_clc_smcd_gid_chid);
990			}
991		}
992	}
993	vec[i].iov_base = trl;
994	vec[i++].iov_len = sizeof(*trl);
995	/* due to the few bytes needed for clc-handshake this cannot block */
996	len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
997	if (len < 0) {
998		smc->sk.sk_err = smc->clcsock->sk->sk_err;
999		reason_code = -smc->sk.sk_err;
1000	} else if (len < ntohs(pclc_base->hdr.length)) {
1001		reason_code = -ENETUNREACH;
1002		smc->sk.sk_err = -reason_code;
1003	}
1004
1005	kfree(pclc);
1006	return reason_code;
1007}
1008
1009/* build and send CLC CONFIRM / ACCEPT message */
1010static int smc_clc_send_confirm_accept(struct smc_sock *smc,
1011				       struct smc_clc_msg_accept_confirm_v2 *clc_v2,
1012				       int first_contact, u8 version,
1013				       u8 *eid, struct smc_init_info *ini)
1014{
1015	struct smc_connection *conn = &smc->conn;
1016	struct smc_clc_first_contact_ext_v2x fce;
1017	struct smcd_dev *smcd = conn->lgr->smcd;
1018	struct smc_clc_msg_accept_confirm *clc;
1019	struct smc_clc_fce_gid_ext gle;
1020	struct smc_clc_msg_trail trl;
1021	int i, len, fce_len;
1022	struct kvec vec[5];
1023	struct msghdr msg;
1024
1025	/* send SMC Confirm CLC msg */
1026	clc = (struct smc_clc_msg_accept_confirm *)clc_v2;
1027	clc->hdr.version = version;	/* SMC version */
1028	if (first_contact)
1029		clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK;
1030	if (conn->lgr->is_smcd) {
1031		/* SMC-D specific settings */
1032		memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
1033		       sizeof(SMCD_EYECATCHER));
1034		clc->hdr.typev1 = SMC_TYPE_D;
1035		clc->d0.gid = htonll(smcd->ops->get_local_gid(smcd));
1036		clc->d0.token = htonll(conn->rmb_desc->token);
1037		clc->d0.dmbe_size = conn->rmbe_size_comp;
1038		clc->d0.dmbe_idx = 0;
1039		memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
1040		if (version == SMC_V1) {
1041			clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
1042		} else {
1043			clc_v2->d1.chid = htons(smc_ism_get_chid(smcd));
1044			if (eid && eid[0])
1045				memcpy(clc_v2->d1.eid, eid, SMC_MAX_EID_LEN);
1046			len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2;
1047			if (first_contact) {
1048				fce_len = smc_clc_fill_fce(&fce, ini);
1049				len += fce_len;
1050			}
1051			clc_v2->hdr.length = htons(len);
1052		}
1053		memcpy(trl.eyecatcher, SMCD_EYECATCHER,
1054		       sizeof(SMCD_EYECATCHER));
1055	} else {
1056		struct smc_link *link = conn->lnk;
1057
1058		/* SMC-R specific settings */
1059		memcpy(clc->hdr.eyecatcher, SMC_EYECATCHER,
1060		       sizeof(SMC_EYECATCHER));
1061		clc->hdr.typev1 = SMC_TYPE_R;
1062		clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
1063		memcpy(clc->r0.lcl.id_for_peer, local_systemid,
1064		       sizeof(local_systemid));
1065		memcpy(&clc->r0.lcl.gid, link->gid, SMC_GID_SIZE);
1066		memcpy(&clc->r0.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
1067		       ETH_ALEN);
1068		hton24(clc->r0.qpn, link->roce_qp->qp_num);
1069		clc->r0.rmb_rkey =
1070			htonl(conn->rmb_desc->mr[link->link_idx]->rkey);
1071		clc->r0.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */
1072		clc->r0.rmbe_alert_token = htonl(conn->alert_token_local);
1073		switch (clc->hdr.type) {
1074		case SMC_CLC_ACCEPT:
1075			clc->r0.qp_mtu = link->path_mtu;
1076			break;
1077		case SMC_CLC_CONFIRM:
1078			clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu);
1079			break;
1080		}
1081		clc->r0.rmbe_size = conn->rmbe_size_comp;
1082		clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ?
1083			cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) :
1084			cpu_to_be64((u64)sg_dma_address
1085				    (conn->rmb_desc->sgt[link->link_idx].sgl));
1086		hton24(clc->r0.psn, link->psn_initial);
1087		if (version == SMC_V1) {
1088			clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
1089		} else {
1090			if (eid && eid[0])
1091				memcpy(clc_v2->r1.eid, eid, SMC_MAX_EID_LEN);
1092			len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2;
1093			if (first_contact) {
1094				fce_len = smc_clc_fill_fce(&fce, ini);
1095				len += fce_len;
1096				fce.fce_v2_base.v2_direct = !link->lgr->uses_gateway;
1097				if (clc->hdr.type == SMC_CLC_CONFIRM) {
1098					memset(&gle, 0, sizeof(gle));
1099					gle.gid_cnt = ini->smcrv2.gidlist.len;
1100					len += sizeof(gle);
1101					len += gle.gid_cnt * sizeof(gle.gid[0]);
1102				}
1103			}
1104			clc_v2->hdr.length = htons(len);
1105		}
1106		memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
1107	}
1108
1109	memset(&msg, 0, sizeof(msg));
1110	i = 0;
1111	vec[i].iov_base = clc_v2;
1112	if (version > SMC_V1)
1113		vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
1114					SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 :
1115					SMCR_CLC_ACCEPT_CONFIRM_LEN_V2) -
1116				   sizeof(trl);
1117	else
1118		vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
1119						SMCD_CLC_ACCEPT_CONFIRM_LEN :
1120						SMCR_CLC_ACCEPT_CONFIRM_LEN) -
1121				   sizeof(trl);
1122	if (version > SMC_V1 && first_contact) {
1123		vec[i].iov_base = &fce;
1124		vec[i++].iov_len = fce_len;
1125		if (!conn->lgr->is_smcd) {
1126			if (clc->hdr.type == SMC_CLC_CONFIRM) {
1127				vec[i].iov_base = &gle;
1128				vec[i++].iov_len = sizeof(gle);
1129				vec[i].iov_base = &ini->smcrv2.gidlist.list;
1130				vec[i++].iov_len = gle.gid_cnt *
1131						   sizeof(gle.gid[0]);
1132			}
1133		}
1134	}
1135	vec[i].iov_base = &trl;
1136	vec[i++].iov_len = sizeof(trl);
1137	return kernel_sendmsg(smc->clcsock, &msg, vec, 1,
1138			      ntohs(clc->hdr.length));
1139}
1140
1141/* send CLC CONFIRM message across internal TCP socket */
1142int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
1143			 u8 version, u8 *eid, struct smc_init_info *ini)
1144{
1145	struct smc_clc_msg_accept_confirm_v2 cclc_v2;
1146	int reason_code = 0;
1147	int len;
1148
1149	/* send SMC Confirm CLC msg */
1150	memset(&cclc_v2, 0, sizeof(cclc_v2));
1151	cclc_v2.hdr.type = SMC_CLC_CONFIRM;
1152	len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact,
1153					  version, eid, ini);
1154	if (len < ntohs(cclc_v2.hdr.length)) {
1155		if (len >= 0) {
1156			reason_code = -ENETUNREACH;
1157			smc->sk.sk_err = -reason_code;
1158		} else {
1159			smc->sk.sk_err = smc->clcsock->sk->sk_err;
1160			reason_code = -smc->sk.sk_err;
1161		}
1162	}
1163	return reason_code;
1164}
1165
1166/* send CLC ACCEPT message across internal TCP socket */
1167int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact,
1168			u8 version, u8 *negotiated_eid, struct smc_init_info *ini)
1169{
1170	struct smc_clc_msg_accept_confirm_v2 aclc_v2;
1171	int len;
1172
1173	memset(&aclc_v2, 0, sizeof(aclc_v2));
1174	aclc_v2.hdr.type = SMC_CLC_ACCEPT;
1175	len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact,
1176					  version, negotiated_eid, ini);
1177	if (len < ntohs(aclc_v2.hdr.length))
1178		len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
1179
1180	return len > 0 ? 0 : len;
1181}
1182
1183int smc_clc_srv_v2x_features_validate(struct smc_clc_msg_proposal *pclc,
1184				      struct smc_init_info *ini)
1185{
1186	struct smc_clc_v2_extension *pclc_v2_ext;
1187
1188	ini->max_conns = SMC_CONN_PER_LGR_MAX;
1189	ini->max_links = SMC_LINKS_ADD_LNK_MAX;
1190
1191	if ((!(ini->smcd_version & SMC_V2) && !(ini->smcr_version & SMC_V2)) ||
1192	    ini->release_nr < SMC_RELEASE_1)
1193		return 0;
1194
1195	pclc_v2_ext = smc_get_clc_v2_ext(pclc);
1196	if (!pclc_v2_ext)
1197		return SMC_CLC_DECL_NOV2EXT;
1198
1199	if (ini->smcr_version & SMC_V2) {
1200		ini->max_conns = min_t(u8, pclc_v2_ext->max_conns, SMC_CONN_PER_LGR_PREFER);
1201		if (ini->max_conns < SMC_CONN_PER_LGR_MIN)
1202			return SMC_CLC_DECL_MAXCONNERR;
1203
1204		ini->max_links = min_t(u8, pclc_v2_ext->max_links, SMC_LINKS_PER_LGR_MAX_PREFER);
1205		if (ini->max_links < SMC_LINKS_ADD_LNK_MIN)
1206			return SMC_CLC_DECL_MAXLINKERR;
1207	}
1208
1209	return 0;
1210}
1211
1212int smc_clc_clnt_v2x_features_validate(struct smc_clc_first_contact_ext *fce,
1213				       struct smc_init_info *ini)
1214{
1215	struct smc_clc_first_contact_ext_v2x *fce_v2x =
1216		(struct smc_clc_first_contact_ext_v2x *)fce;
1217
1218	if (ini->release_nr < SMC_RELEASE_1)
1219		return 0;
1220
1221	if (!ini->is_smcd) {
1222		if (fce_v2x->max_conns < SMC_CONN_PER_LGR_MIN)
1223			return SMC_CLC_DECL_MAXCONNERR;
1224		ini->max_conns = fce_v2x->max_conns;
1225
1226		if (fce_v2x->max_links > SMC_LINKS_ADD_LNK_MAX ||
1227		    fce_v2x->max_links < SMC_LINKS_ADD_LNK_MIN)
1228			return SMC_CLC_DECL_MAXLINKERR;
1229		ini->max_links = fce_v2x->max_links;
1230	}
1231
1232	return 0;
1233}
1234
1235int smc_clc_v2x_features_confirm_check(struct smc_clc_msg_accept_confirm *cclc,
1236				       struct smc_init_info *ini)
1237{
1238	struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
1239		(struct smc_clc_msg_accept_confirm_v2 *)cclc;
1240	struct smc_clc_first_contact_ext *fce =
1241		smc_get_clc_first_contact_ext(clc_v2, ini->is_smcd);
1242	struct smc_clc_first_contact_ext_v2x *fce_v2x =
1243		(struct smc_clc_first_contact_ext_v2x *)fce;
1244
1245	if (cclc->hdr.version == SMC_V1 ||
1246	    !(cclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK))
1247		return 0;
1248
1249	if (ini->release_nr != fce->release)
1250		return SMC_CLC_DECL_RELEASEERR;
1251
1252	if (fce->release < SMC_RELEASE_1)
1253		return 0;
1254
1255	if (!ini->is_smcd) {
1256		if (fce_v2x->max_conns != ini->max_conns)
1257			return SMC_CLC_DECL_MAXCONNERR;
1258		if (fce_v2x->max_links != ini->max_links)
1259			return SMC_CLC_DECL_MAXLINKERR;
1260	}
1261
1262	return 0;
1263}
1264
1265void smc_clc_get_hostname(u8 **host)
1266{
1267	*host = &smc_hostname[0];
1268}
1269
1270void __init smc_clc_init(void)
1271{
1272	struct new_utsname *u;
1273
1274	memset(smc_hostname, _S, sizeof(smc_hostname)); /* ASCII blanks */
1275	u = utsname();
1276	memcpy(smc_hostname, u->nodename,
1277	       min_t(size_t, strlen(u->nodename), sizeof(smc_hostname)));
1278
1279	INIT_LIST_HEAD(&smc_clc_eid_table.list);
1280	rwlock_init(&smc_clc_eid_table.lock);
1281	smc_clc_eid_table.ueid_cnt = 0;
1282#if IS_ENABLED(CONFIG_S390)
1283	smc_clc_eid_table.seid_enabled = 1;
1284#else
1285	smc_clc_eid_table.seid_enabled = 0;
1286#endif
1287}
1288
1289void smc_clc_exit(void)
1290{
1291	smc_clc_ueid_remove(NULL);
1292}
1293