Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Shared Memory Communications over RDMA (SMC-R) and RoCE
0004  *
0005  *  CLC (connection layer control) handshake over initial TCP socket to
0006  *  prepare for RDMA traffic
0007  *
0008  *  Copyright IBM Corp. 2016, 2018
0009  *
0010  *  Author(s):  Ursula Braun <ubraun@linux.vnet.ibm.com>
0011  */
0012 
0013 #include <linux/in.h>
0014 #include <linux/inetdevice.h>
0015 #include <linux/if_ether.h>
0016 #include <linux/sched/signal.h>
0017 #include <linux/utsname.h>
0018 #include <linux/ctype.h>
0019 
0020 #include <net/addrconf.h>
0021 #include <net/sock.h>
0022 #include <net/tcp.h>
0023 
0024 #include "smc.h"
0025 #include "smc_core.h"
0026 #include "smc_clc.h"
0027 #include "smc_ib.h"
0028 #include "smc_ism.h"
0029 #include "smc_netlink.h"
0030 
0031 #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
0032 #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
0033 #define SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 78
0034 #define SMCR_CLC_ACCEPT_CONFIRM_LEN_V2 108
0035 #define SMC_CLC_RECV_BUF_LEN    100
0036 
0037 /* eye catcher "SMCR" EBCDIC for CLC messages */
0038 static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
0039 /* eye catcher "SMCD" EBCDIC for CLC messages */
0040 static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
0041 
0042 static u8 smc_hostname[SMC_MAX_HOSTNAME_LEN];
0043 
0044 struct smc_clc_eid_table {
0045     rwlock_t lock;
0046     struct list_head list;
0047     u8 ueid_cnt;
0048     u8 seid_enabled;
0049 };
0050 
0051 static struct smc_clc_eid_table smc_clc_eid_table;
0052 
0053 struct smc_clc_eid_entry {
0054     struct list_head list;
0055     u8 eid[SMC_MAX_EID_LEN];
0056 };
0057 
0058 /* The size of a user EID is 32 characters.
0059  * Valid characters should be (single-byte character set) A-Z, 0-9, '.' and '-'.
0060  * Blanks should only be used to pad to the expected size.
0061  * First character must be alphanumeric.
0062  */
0063 static bool smc_clc_ueid_valid(char *ueid)
0064 {
0065     char *end = ueid + SMC_MAX_EID_LEN;
0066 
0067     while (--end >= ueid && isspace(*end))
0068         ;
0069     if (end < ueid)
0070         return false;
0071     if (!isalnum(*ueid) || islower(*ueid))
0072         return false;
0073     while (ueid <= end) {
0074         if ((!isalnum(*ueid) || islower(*ueid)) && *ueid != '.' &&
0075             *ueid != '-')
0076             return false;
0077         ueid++;
0078     }
0079     return true;
0080 }
0081 
0082 static int smc_clc_ueid_add(char *ueid)
0083 {
0084     struct smc_clc_eid_entry *new_ueid, *tmp_ueid;
0085     int rc;
0086 
0087     if (!smc_clc_ueid_valid(ueid))
0088         return -EINVAL;
0089 
0090     /* add a new ueid entry to the ueid table if there isn't one */
0091     new_ueid = kzalloc(sizeof(*new_ueid), GFP_KERNEL);
0092     if (!new_ueid)
0093         return -ENOMEM;
0094     memcpy(new_ueid->eid, ueid, SMC_MAX_EID_LEN);
0095 
0096     write_lock(&smc_clc_eid_table.lock);
0097     if (smc_clc_eid_table.ueid_cnt >= SMC_MAX_UEID) {
0098         rc = -ERANGE;
0099         goto err_out;
0100     }
0101     list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) {
0102         if (!memcmp(tmp_ueid->eid, ueid, SMC_MAX_EID_LEN)) {
0103             rc = -EEXIST;
0104             goto err_out;
0105         }
0106     }
0107     list_add_tail(&new_ueid->list, &smc_clc_eid_table.list);
0108     smc_clc_eid_table.ueid_cnt++;
0109     write_unlock(&smc_clc_eid_table.lock);
0110     return 0;
0111 
0112 err_out:
0113     write_unlock(&smc_clc_eid_table.lock);
0114     kfree(new_ueid);
0115     return rc;
0116 }
0117 
0118 int smc_clc_ueid_count(void)
0119 {
0120     int count;
0121 
0122     read_lock(&smc_clc_eid_table.lock);
0123     count = smc_clc_eid_table.ueid_cnt;
0124     read_unlock(&smc_clc_eid_table.lock);
0125 
0126     return count;
0127 }
0128 
0129 int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info)
0130 {
0131     struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY];
0132     char *ueid;
0133 
0134     if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1)
0135         return -EINVAL;
0136     ueid = (char *)nla_data(nla_ueid);
0137 
0138     return smc_clc_ueid_add(ueid);
0139 }
0140 
0141 /* remove one or all ueid entries from the table */
0142 static int smc_clc_ueid_remove(char *ueid)
0143 {
0144     struct smc_clc_eid_entry *lst_ueid, *tmp_ueid;
0145     int rc = -ENOENT;
0146 
0147     /* remove table entry */
0148     write_lock(&smc_clc_eid_table.lock);
0149     list_for_each_entry_safe(lst_ueid, tmp_ueid, &smc_clc_eid_table.list,
0150                  list) {
0151         if (!ueid || !memcmp(lst_ueid->eid, ueid, SMC_MAX_EID_LEN)) {
0152             list_del(&lst_ueid->list);
0153             smc_clc_eid_table.ueid_cnt--;
0154             kfree(lst_ueid);
0155             rc = 0;
0156         }
0157     }
0158     if (!rc && !smc_clc_eid_table.ueid_cnt) {
0159         smc_clc_eid_table.seid_enabled = 1;
0160         rc = -EAGAIN;   /* indicate success and enabling of seid */
0161     }
0162     write_unlock(&smc_clc_eid_table.lock);
0163     return rc;
0164 }
0165 
0166 int smc_nl_remove_ueid(struct sk_buff *skb, struct genl_info *info)
0167 {
0168     struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY];
0169     char *ueid;
0170 
0171     if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1)
0172         return -EINVAL;
0173     ueid = (char *)nla_data(nla_ueid);
0174 
0175     return smc_clc_ueid_remove(ueid);
0176 }
0177 
0178 int smc_nl_flush_ueid(struct sk_buff *skb, struct genl_info *info)
0179 {
0180     smc_clc_ueid_remove(NULL);
0181     return 0;
0182 }
0183 
0184 static int smc_nl_ueid_dumpinfo(struct sk_buff *skb, u32 portid, u32 seq,
0185                 u32 flags, char *ueid)
0186 {
0187     char ueid_str[SMC_MAX_EID_LEN + 1];
0188     void *hdr;
0189 
0190     hdr = genlmsg_put(skb, portid, seq, &smc_gen_nl_family,
0191               flags, SMC_NETLINK_DUMP_UEID);
0192     if (!hdr)
0193         return -ENOMEM;
0194     memcpy(ueid_str, ueid, SMC_MAX_EID_LEN);
0195     ueid_str[SMC_MAX_EID_LEN] = 0;
0196     if (nla_put_string(skb, SMC_NLA_EID_TABLE_ENTRY, ueid_str)) {
0197         genlmsg_cancel(skb, hdr);
0198         return -EMSGSIZE;
0199     }
0200     genlmsg_end(skb, hdr);
0201     return 0;
0202 }
0203 
0204 static int _smc_nl_ueid_dump(struct sk_buff *skb, u32 portid, u32 seq,
0205                  int start_idx)
0206 {
0207     struct smc_clc_eid_entry *lst_ueid;
0208     int idx = 0;
0209 
0210     read_lock(&smc_clc_eid_table.lock);
0211     list_for_each_entry(lst_ueid, &smc_clc_eid_table.list, list) {
0212         if (idx++ < start_idx)
0213             continue;
0214         if (smc_nl_ueid_dumpinfo(skb, portid, seq, NLM_F_MULTI,
0215                      lst_ueid->eid)) {
0216             --idx;
0217             break;
0218         }
0219     }
0220     read_unlock(&smc_clc_eid_table.lock);
0221     return idx;
0222 }
0223 
0224 int smc_nl_dump_ueid(struct sk_buff *skb, struct netlink_callback *cb)
0225 {
0226     struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
0227     int idx;
0228 
0229     idx = _smc_nl_ueid_dump(skb, NETLINK_CB(cb->skb).portid,
0230                 cb->nlh->nlmsg_seq, cb_ctx->pos[0]);
0231 
0232     cb_ctx->pos[0] = idx;
0233     return skb->len;
0234 }
0235 
0236 int smc_nl_dump_seid(struct sk_buff *skb, struct netlink_callback *cb)
0237 {
0238     struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
0239     char seid_str[SMC_MAX_EID_LEN + 1];
0240     u8 seid_enabled;
0241     void *hdr;
0242     u8 *seid;
0243 
0244     if (cb_ctx->pos[0])
0245         return skb->len;
0246 
0247     hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
0248               &smc_gen_nl_family, NLM_F_MULTI,
0249               SMC_NETLINK_DUMP_SEID);
0250     if (!hdr)
0251         return -ENOMEM;
0252     if (!smc_ism_is_v2_capable())
0253         goto end;
0254 
0255     smc_ism_get_system_eid(&seid);
0256     memcpy(seid_str, seid, SMC_MAX_EID_LEN);
0257     seid_str[SMC_MAX_EID_LEN] = 0;
0258     if (nla_put_string(skb, SMC_NLA_SEID_ENTRY, seid_str))
0259         goto err;
0260     read_lock(&smc_clc_eid_table.lock);
0261     seid_enabled = smc_clc_eid_table.seid_enabled;
0262     read_unlock(&smc_clc_eid_table.lock);
0263     if (nla_put_u8(skb, SMC_NLA_SEID_ENABLED, seid_enabled))
0264         goto err;
0265 end:
0266     genlmsg_end(skb, hdr);
0267     cb_ctx->pos[0]++;
0268     return skb->len;
0269 err:
0270     genlmsg_cancel(skb, hdr);
0271     return -EMSGSIZE;
0272 }
0273 
0274 int smc_nl_enable_seid(struct sk_buff *skb, struct genl_info *info)
0275 {
0276     write_lock(&smc_clc_eid_table.lock);
0277     smc_clc_eid_table.seid_enabled = 1;
0278     write_unlock(&smc_clc_eid_table.lock);
0279     return 0;
0280 }
0281 
0282 int smc_nl_disable_seid(struct sk_buff *skb, struct genl_info *info)
0283 {
0284     int rc = 0;
0285 
0286     write_lock(&smc_clc_eid_table.lock);
0287     if (!smc_clc_eid_table.ueid_cnt)
0288         rc = -ENOENT;
0289     else
0290         smc_clc_eid_table.seid_enabled = 0;
0291     write_unlock(&smc_clc_eid_table.lock);
0292     return rc;
0293 }
0294 
0295 static bool _smc_clc_match_ueid(u8 *peer_ueid)
0296 {
0297     struct smc_clc_eid_entry *tmp_ueid;
0298 
0299     list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) {
0300         if (!memcmp(tmp_ueid->eid, peer_ueid, SMC_MAX_EID_LEN))
0301             return true;
0302     }
0303     return false;
0304 }
0305 
0306 bool smc_clc_match_eid(u8 *negotiated_eid,
0307                struct smc_clc_v2_extension *smc_v2_ext,
0308                u8 *peer_eid, u8 *local_eid)
0309 {
0310     bool match = false;
0311     int i;
0312 
0313     negotiated_eid[0] = 0;
0314     read_lock(&smc_clc_eid_table.lock);
0315     if (peer_eid && local_eid &&
0316         smc_clc_eid_table.seid_enabled &&
0317         smc_v2_ext->hdr.flag.seid &&
0318         !memcmp(peer_eid, local_eid, SMC_MAX_EID_LEN)) {
0319         memcpy(negotiated_eid, peer_eid, SMC_MAX_EID_LEN);
0320         match = true;
0321         goto out;
0322     }
0323 
0324     for (i = 0; i < smc_v2_ext->hdr.eid_cnt; i++) {
0325         if (_smc_clc_match_ueid(smc_v2_ext->user_eids[i])) {
0326             memcpy(negotiated_eid, smc_v2_ext->user_eids[i],
0327                    SMC_MAX_EID_LEN);
0328             match = true;
0329             goto out;
0330         }
0331     }
0332 out:
0333     read_unlock(&smc_clc_eid_table.lock);
0334     return match;
0335 }
0336 
0337 /* check arriving CLC proposal */
0338 static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)
0339 {
0340     struct smc_clc_msg_proposal_prefix *pclc_prfx;
0341     struct smc_clc_smcd_v2_extension *smcd_v2_ext;
0342     struct smc_clc_msg_hdr *hdr = &pclc->hdr;
0343     struct smc_clc_v2_extension *v2_ext;
0344 
0345     v2_ext = smc_get_clc_v2_ext(pclc);
0346     pclc_prfx = smc_clc_proposal_get_prefix(pclc);
0347     if (hdr->version == SMC_V1) {
0348         if (hdr->typev1 == SMC_TYPE_N)
0349             return false;
0350         if (ntohs(hdr->length) !=
0351             sizeof(*pclc) + ntohs(pclc->iparea_offset) +
0352             sizeof(*pclc_prfx) +
0353             pclc_prfx->ipv6_prefixes_cnt *
0354                 sizeof(struct smc_clc_ipv6_prefix) +
0355             sizeof(struct smc_clc_msg_trail))
0356             return false;
0357     } else {
0358         if (ntohs(hdr->length) !=
0359             sizeof(*pclc) +
0360             sizeof(struct smc_clc_msg_smcd) +
0361             (hdr->typev1 != SMC_TYPE_N ?
0362                 sizeof(*pclc_prfx) +
0363                 pclc_prfx->ipv6_prefixes_cnt *
0364                 sizeof(struct smc_clc_ipv6_prefix) : 0) +
0365             (hdr->typev2 != SMC_TYPE_N ?
0366                 sizeof(*v2_ext) +
0367                 v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN : 0) +
0368             (smcd_indicated(hdr->typev2) ?
0369                 sizeof(*smcd_v2_ext) + v2_ext->hdr.ism_gid_cnt *
0370                     sizeof(struct smc_clc_smcd_gid_chid) :
0371                 0) +
0372             sizeof(struct smc_clc_msg_trail))
0373             return false;
0374     }
0375     return true;
0376 }
0377 
0378 /* check arriving CLC accept or confirm */
0379 static bool
0380 smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2)
0381 {
0382     struct smc_clc_msg_hdr *hdr = &clc_v2->hdr;
0383 
0384     if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
0385         return false;
0386     if (hdr->version == SMC_V1) {
0387         if ((hdr->typev1 == SMC_TYPE_R &&
0388              ntohs(hdr->length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
0389             (hdr->typev1 == SMC_TYPE_D &&
0390              ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
0391             return false;
0392     } else {
0393         if (hdr->typev1 == SMC_TYPE_D &&
0394             ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 &&
0395             (ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 +
0396                 sizeof(struct smc_clc_first_contact_ext)))
0397             return false;
0398         if (hdr->typev1 == SMC_TYPE_R &&
0399             ntohs(hdr->length) < SMCR_CLC_ACCEPT_CONFIRM_LEN_V2)
0400             return false;
0401     }
0402     return true;
0403 }
0404 
0405 /* check arriving CLC decline */
0406 static bool
0407 smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc)
0408 {
0409     struct smc_clc_msg_hdr *hdr = &dclc->hdr;
0410 
0411     if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
0412         return false;
0413     if (hdr->version == SMC_V1) {
0414         if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline))
0415             return false;
0416     } else {
0417         if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline_v2))
0418             return false;
0419     }
0420     return true;
0421 }
0422 
0423 static void smc_clc_fill_fce(struct smc_clc_first_contact_ext *fce, int *len)
0424 {
0425     memset(fce, 0, sizeof(*fce));
0426     fce->os_type = SMC_CLC_OS_LINUX;
0427     fce->release = SMC_RELEASE;
0428     memcpy(fce->hostname, smc_hostname, sizeof(smc_hostname));
0429     (*len) += sizeof(*fce);
0430 }
0431 
0432 /* check if received message has a correct header length and contains valid
0433  * heading and trailing eyecatchers
0434  */
0435 static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
0436 {
0437     struct smc_clc_msg_accept_confirm_v2 *clc_v2;
0438     struct smc_clc_msg_proposal *pclc;
0439     struct smc_clc_msg_decline *dclc;
0440     struct smc_clc_msg_trail *trl;
0441 
0442     if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
0443         memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
0444         return false;
0445     switch (clcm->type) {
0446     case SMC_CLC_PROPOSAL:
0447         pclc = (struct smc_clc_msg_proposal *)clcm;
0448         if (!smc_clc_msg_prop_valid(pclc))
0449             return false;
0450         trl = (struct smc_clc_msg_trail *)
0451             ((u8 *)pclc + ntohs(pclc->hdr.length) - sizeof(*trl));
0452         break;
0453     case SMC_CLC_ACCEPT:
0454     case SMC_CLC_CONFIRM:
0455         clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm;
0456         if (!smc_clc_msg_acc_conf_valid(clc_v2))
0457             return false;
0458         trl = (struct smc_clc_msg_trail *)
0459             ((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) -
0460                             sizeof(*trl));
0461         break;
0462     case SMC_CLC_DECLINE:
0463         dclc = (struct smc_clc_msg_decline *)clcm;
0464         if (!smc_clc_msg_decl_valid(dclc))
0465             return false;
0466         check_trl = false;
0467         break;
0468     default:
0469         return false;
0470     }
0471     if (check_trl &&
0472         memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
0473         memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
0474         return false;
0475     return true;
0476 }
0477 
0478 /* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */
0479 static int smc_clc_prfx_set4_rcu(struct dst_entry *dst, __be32 ipv4,
0480                  struct smc_clc_msg_proposal_prefix *prop)
0481 {
0482     struct in_device *in_dev = __in_dev_get_rcu(dst->dev);
0483     const struct in_ifaddr *ifa;
0484 
0485     if (!in_dev)
0486         return -ENODEV;
0487 
0488     in_dev_for_each_ifa_rcu(ifa, in_dev) {
0489         if (!inet_ifa_match(ipv4, ifa))
0490             continue;
0491         prop->prefix_len = inet_mask_len(ifa->ifa_mask);
0492         prop->outgoing_subnet = ifa->ifa_address & ifa->ifa_mask;
0493         /* prop->ipv6_prefixes_cnt = 0; already done by memset before */
0494         return 0;
0495     }
0496     return -ENOENT;
0497 }
0498 
0499 /* fill CLC proposal msg with ipv6 prefixes from device */
0500 static int smc_clc_prfx_set6_rcu(struct dst_entry *dst,
0501                  struct smc_clc_msg_proposal_prefix *prop,
0502                  struct smc_clc_ipv6_prefix *ipv6_prfx)
0503 {
0504 #if IS_ENABLED(CONFIG_IPV6)
0505     struct inet6_dev *in6_dev = __in6_dev_get(dst->dev);
0506     struct inet6_ifaddr *ifa;
0507     int cnt = 0;
0508 
0509     if (!in6_dev)
0510         return -ENODEV;
0511     /* use a maximum of 8 IPv6 prefixes from device */
0512     list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
0513         if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)
0514             continue;
0515         ipv6_addr_prefix(&ipv6_prfx[cnt].prefix,
0516                  &ifa->addr, ifa->prefix_len);
0517         ipv6_prfx[cnt].prefix_len = ifa->prefix_len;
0518         cnt++;
0519         if (cnt == SMC_CLC_MAX_V6_PREFIX)
0520             break;
0521     }
0522     prop->ipv6_prefixes_cnt = cnt;
0523     if (cnt)
0524         return 0;
0525 #endif
0526     return -ENOENT;
0527 }
0528 
0529 /* retrieve and set prefixes in CLC proposal msg */
0530 static int smc_clc_prfx_set(struct socket *clcsock,
0531                 struct smc_clc_msg_proposal_prefix *prop,
0532                 struct smc_clc_ipv6_prefix *ipv6_prfx)
0533 {
0534     struct dst_entry *dst = sk_dst_get(clcsock->sk);
0535     struct sockaddr_storage addrs;
0536     struct sockaddr_in6 *addr6;
0537     struct sockaddr_in *addr;
0538     int rc = -ENOENT;
0539 
0540     if (!dst) {
0541         rc = -ENOTCONN;
0542         goto out;
0543     }
0544     if (!dst->dev) {
0545         rc = -ENODEV;
0546         goto out_rel;
0547     }
0548     /* get address to which the internal TCP socket is bound */
0549     if (kernel_getsockname(clcsock, (struct sockaddr *)&addrs) < 0)
0550         goto out_rel;
0551     /* analyze IP specific data of net_device belonging to TCP socket */
0552     addr6 = (struct sockaddr_in6 *)&addrs;
0553     rcu_read_lock();
0554     if (addrs.ss_family == PF_INET) {
0555         /* IPv4 */
0556         addr = (struct sockaddr_in *)&addrs;
0557         rc = smc_clc_prfx_set4_rcu(dst, addr->sin_addr.s_addr, prop);
0558     } else if (ipv6_addr_v4mapped(&addr6->sin6_addr)) {
0559         /* mapped IPv4 address - peer is IPv4 only */
0560         rc = smc_clc_prfx_set4_rcu(dst, addr6->sin6_addr.s6_addr32[3],
0561                        prop);
0562     } else {
0563         /* IPv6 */
0564         rc = smc_clc_prfx_set6_rcu(dst, prop, ipv6_prfx);
0565     }
0566     rcu_read_unlock();
0567 out_rel:
0568     dst_release(dst);
0569 out:
0570     return rc;
0571 }
0572 
0573 /* match ipv4 addrs of dev against addr in CLC proposal */
0574 static int smc_clc_prfx_match4_rcu(struct net_device *dev,
0575                    struct smc_clc_msg_proposal_prefix *prop)
0576 {
0577     struct in_device *in_dev = __in_dev_get_rcu(dev);
0578     const struct in_ifaddr *ifa;
0579 
0580     if (!in_dev)
0581         return -ENODEV;
0582     in_dev_for_each_ifa_rcu(ifa, in_dev) {
0583         if (prop->prefix_len == inet_mask_len(ifa->ifa_mask) &&
0584             inet_ifa_match(prop->outgoing_subnet, ifa))
0585             return 0;
0586     }
0587 
0588     return -ENOENT;
0589 }
0590 
0591 /* match ipv6 addrs of dev against addrs in CLC proposal */
0592 static int smc_clc_prfx_match6_rcu(struct net_device *dev,
0593                    struct smc_clc_msg_proposal_prefix *prop)
0594 {
0595 #if IS_ENABLED(CONFIG_IPV6)
0596     struct inet6_dev *in6_dev = __in6_dev_get(dev);
0597     struct smc_clc_ipv6_prefix *ipv6_prfx;
0598     struct inet6_ifaddr *ifa;
0599     int i, max;
0600 
0601     if (!in6_dev)
0602         return -ENODEV;
0603     /* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */
0604     ipv6_prfx = (struct smc_clc_ipv6_prefix *)((u8 *)prop + sizeof(*prop));
0605     max = min_t(u8, prop->ipv6_prefixes_cnt, SMC_CLC_MAX_V6_PREFIX);
0606     list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
0607         if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)
0608             continue;
0609         for (i = 0; i < max; i++) {
0610             if (ifa->prefix_len == ipv6_prfx[i].prefix_len &&
0611                 ipv6_prefix_equal(&ifa->addr, &ipv6_prfx[i].prefix,
0612                           ifa->prefix_len))
0613                 return 0;
0614         }
0615     }
0616 #endif
0617     return -ENOENT;
0618 }
0619 
0620 /* check if proposed prefixes match one of our device prefixes */
0621 int smc_clc_prfx_match(struct socket *clcsock,
0622                struct smc_clc_msg_proposal_prefix *prop)
0623 {
0624     struct dst_entry *dst = sk_dst_get(clcsock->sk);
0625     int rc;
0626 
0627     if (!dst) {
0628         rc = -ENOTCONN;
0629         goto out;
0630     }
0631     if (!dst->dev) {
0632         rc = -ENODEV;
0633         goto out_rel;
0634     }
0635     rcu_read_lock();
0636     if (!prop->ipv6_prefixes_cnt)
0637         rc = smc_clc_prfx_match4_rcu(dst->dev, prop);
0638     else
0639         rc = smc_clc_prfx_match6_rcu(dst->dev, prop);
0640     rcu_read_unlock();
0641 out_rel:
0642     dst_release(dst);
0643 out:
0644     return rc;
0645 }
0646 
0647 /* Wait for data on the tcp-socket, analyze received data
0648  * Returns:
0649  * 0 if success and it was not a decline that we received.
0650  * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send.
0651  * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
0652  */
0653 int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
0654              u8 expected_type, unsigned long timeout)
0655 {
0656     long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo;
0657     struct sock *clc_sk = smc->clcsock->sk;
0658     struct smc_clc_msg_hdr *clcm = buf;
0659     struct msghdr msg = {NULL, 0};
0660     int reason_code = 0;
0661     struct kvec vec = {buf, buflen};
0662     int len, datlen, recvlen;
0663     bool check_trl = true;
0664     int krflags;
0665 
0666     /* peek the first few bytes to determine length of data to receive
0667      * so we don't consume any subsequent CLC message or payload data
0668      * in the TCP byte stream
0669      */
0670     /*
0671      * Caller must make sure that buflen is no less than
0672      * sizeof(struct smc_clc_msg_hdr)
0673      */
0674     krflags = MSG_PEEK | MSG_WAITALL;
0675     clc_sk->sk_rcvtimeo = timeout;
0676     iov_iter_kvec(&msg.msg_iter, READ, &vec, 1,
0677             sizeof(struct smc_clc_msg_hdr));
0678     len = sock_recvmsg(smc->clcsock, &msg, krflags);
0679     if (signal_pending(current)) {
0680         reason_code = -EINTR;
0681         clc_sk->sk_err = EINTR;
0682         smc->sk.sk_err = EINTR;
0683         goto out;
0684     }
0685     if (clc_sk->sk_err) {
0686         reason_code = -clc_sk->sk_err;
0687         if (clc_sk->sk_err == EAGAIN &&
0688             expected_type == SMC_CLC_DECLINE)
0689             clc_sk->sk_err = 0; /* reset for fallback usage */
0690         else
0691             smc->sk.sk_err = clc_sk->sk_err;
0692         goto out;
0693     }
0694     if (!len) { /* peer has performed orderly shutdown */
0695         smc->sk.sk_err = ECONNRESET;
0696         reason_code = -ECONNRESET;
0697         goto out;
0698     }
0699     if (len < 0) {
0700         if (len != -EAGAIN || expected_type != SMC_CLC_DECLINE)
0701             smc->sk.sk_err = -len;
0702         reason_code = len;
0703         goto out;
0704     }
0705     datlen = ntohs(clcm->length);
0706     if ((len < sizeof(struct smc_clc_msg_hdr)) ||
0707         (clcm->version < SMC_V1) ||
0708         ((clcm->type != SMC_CLC_DECLINE) &&
0709          (clcm->type != expected_type))) {
0710         smc->sk.sk_err = EPROTO;
0711         reason_code = -EPROTO;
0712         goto out;
0713     }
0714 
0715     /* receive the complete CLC message */
0716     memset(&msg, 0, sizeof(struct msghdr));
0717     if (datlen > buflen) {
0718         check_trl = false;
0719         recvlen = buflen;
0720     } else {
0721         recvlen = datlen;
0722     }
0723     iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);
0724     krflags = MSG_WAITALL;
0725     len = sock_recvmsg(smc->clcsock, &msg, krflags);
0726     if (len < recvlen || !smc_clc_msg_hdr_valid(clcm, check_trl)) {
0727         smc->sk.sk_err = EPROTO;
0728         reason_code = -EPROTO;
0729         goto out;
0730     }
0731     datlen -= len;
0732     while (datlen) {
0733         u8 tmp[SMC_CLC_RECV_BUF_LEN];
0734 
0735         vec.iov_base = &tmp;
0736         vec.iov_len = SMC_CLC_RECV_BUF_LEN;
0737         /* receive remaining proposal message */
0738         recvlen = datlen > SMC_CLC_RECV_BUF_LEN ?
0739                         SMC_CLC_RECV_BUF_LEN : datlen;
0740         iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);
0741         len = sock_recvmsg(smc->clcsock, &msg, krflags);
0742         datlen -= len;
0743     }
0744     if (clcm->type == SMC_CLC_DECLINE) {
0745         struct smc_clc_msg_decline *dclc;
0746 
0747         dclc = (struct smc_clc_msg_decline *)clcm;
0748         reason_code = SMC_CLC_DECL_PEERDECL;
0749         smc->peer_diagnosis = ntohl(dclc->peer_diagnosis);
0750         if (((struct smc_clc_msg_decline *)buf)->hdr.typev2 &
0751                         SMC_FIRST_CONTACT_MASK) {
0752             smc->conn.lgr->sync_err = 1;
0753             smc_lgr_terminate_sched(smc->conn.lgr);
0754         }
0755     }
0756 
0757 out:
0758     clc_sk->sk_rcvtimeo = rcvtimeo;
0759     return reason_code;
0760 }
0761 
0762 /* send CLC DECLINE message across internal TCP socket */
0763 int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version)
0764 {
0765     struct smc_clc_msg_decline *dclc_v1;
0766     struct smc_clc_msg_decline_v2 dclc;
0767     struct msghdr msg;
0768     int len, send_len;
0769     struct kvec vec;
0770 
0771     dclc_v1 = (struct smc_clc_msg_decline *)&dclc;
0772     memset(&dclc, 0, sizeof(dclc));
0773     memcpy(dclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
0774     dclc.hdr.type = SMC_CLC_DECLINE;
0775     dclc.hdr.version = version;
0776     dclc.os_type = version == SMC_V1 ? 0 : SMC_CLC_OS_LINUX;
0777     dclc.hdr.typev2 = (peer_diag_info == SMC_CLC_DECL_SYNCERR) ?
0778                         SMC_FIRST_CONTACT_MASK : 0;
0779     if ((!smc_conn_lgr_valid(&smc->conn) || !smc->conn.lgr->is_smcd) &&
0780         smc_ib_is_valid_local_systemid())
0781         memcpy(dclc.id_for_peer, local_systemid,
0782                sizeof(local_systemid));
0783     dclc.peer_diagnosis = htonl(peer_diag_info);
0784     if (version == SMC_V1) {
0785         memcpy(dclc_v1->trl.eyecatcher, SMC_EYECATCHER,
0786                sizeof(SMC_EYECATCHER));
0787         send_len = sizeof(*dclc_v1);
0788     } else {
0789         memcpy(dclc.trl.eyecatcher, SMC_EYECATCHER,
0790                sizeof(SMC_EYECATCHER));
0791         send_len = sizeof(dclc);
0792     }
0793     dclc.hdr.length = htons(send_len);
0794 
0795     memset(&msg, 0, sizeof(msg));
0796     vec.iov_base = &dclc;
0797     vec.iov_len = send_len;
0798     len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, send_len);
0799     if (len < 0 || len < send_len)
0800         len = -EPROTO;
0801     return len > 0 ? 0 : len;
0802 }
0803 
0804 /* send CLC PROPOSAL message across internal TCP socket */
0805 int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
0806 {
0807     struct smc_clc_smcd_v2_extension *smcd_v2_ext;
0808     struct smc_clc_msg_proposal_prefix *pclc_prfx;
0809     struct smc_clc_msg_proposal *pclc_base;
0810     struct smc_clc_smcd_gid_chid *gidchids;
0811     struct smc_clc_msg_proposal_area *pclc;
0812     struct smc_clc_ipv6_prefix *ipv6_prfx;
0813     struct smc_clc_v2_extension *v2_ext;
0814     struct smc_clc_msg_smcd *pclc_smcd;
0815     struct smc_clc_msg_trail *trl;
0816     int len, i, plen, rc;
0817     int reason_code = 0;
0818     struct kvec vec[8];
0819     struct msghdr msg;
0820 
0821     pclc = kzalloc(sizeof(*pclc), GFP_KERNEL);
0822     if (!pclc)
0823         return -ENOMEM;
0824 
0825     pclc_base = &pclc->pclc_base;
0826     pclc_smcd = &pclc->pclc_smcd;
0827     pclc_prfx = &pclc->pclc_prfx;
0828     ipv6_prfx = pclc->pclc_prfx_ipv6;
0829     v2_ext = &pclc->pclc_v2_ext;
0830     smcd_v2_ext = &pclc->pclc_smcd_v2_ext;
0831     gidchids = pclc->pclc_gidchids;
0832     trl = &pclc->pclc_trl;
0833 
0834     pclc_base->hdr.version = SMC_V2;
0835     pclc_base->hdr.typev1 = ini->smc_type_v1;
0836     pclc_base->hdr.typev2 = ini->smc_type_v2;
0837     plen = sizeof(*pclc_base) + sizeof(*pclc_smcd) + sizeof(*trl);
0838 
0839     /* retrieve ip prefixes for CLC proposal msg */
0840     if (ini->smc_type_v1 != SMC_TYPE_N) {
0841         rc = smc_clc_prfx_set(smc->clcsock, pclc_prfx, ipv6_prfx);
0842         if (rc) {
0843             if (ini->smc_type_v2 == SMC_TYPE_N) {
0844                 kfree(pclc);
0845                 return SMC_CLC_DECL_CNFERR;
0846             }
0847             pclc_base->hdr.typev1 = SMC_TYPE_N;
0848         } else {
0849             pclc_base->iparea_offset = htons(sizeof(*pclc_smcd));
0850             plen += sizeof(*pclc_prfx) +
0851                     pclc_prfx->ipv6_prefixes_cnt *
0852                     sizeof(ipv6_prfx[0]);
0853         }
0854     }
0855 
0856     /* build SMC Proposal CLC message */
0857     memcpy(pclc_base->hdr.eyecatcher, SMC_EYECATCHER,
0858            sizeof(SMC_EYECATCHER));
0859     pclc_base->hdr.type = SMC_CLC_PROPOSAL;
0860     if (smcr_indicated(ini->smc_type_v1)) {
0861         /* add SMC-R specifics */
0862         memcpy(pclc_base->lcl.id_for_peer, local_systemid,
0863                sizeof(local_systemid));
0864         memcpy(pclc_base->lcl.gid, ini->ib_gid, SMC_GID_SIZE);
0865         memcpy(pclc_base->lcl.mac, &ini->ib_dev->mac[ini->ib_port - 1],
0866                ETH_ALEN);
0867     }
0868     if (smcd_indicated(ini->smc_type_v1)) {
0869         /* add SMC-D specifics */
0870         if (ini->ism_dev[0]) {
0871             pclc_smcd->ism.gid = htonll(ini->ism_dev[0]->local_gid);
0872             pclc_smcd->ism.chid =
0873                 htons(smc_ism_get_chid(ini->ism_dev[0]));
0874         }
0875     }
0876     if (ini->smc_type_v2 == SMC_TYPE_N) {
0877         pclc_smcd->v2_ext_offset = 0;
0878     } else {
0879         struct smc_clc_eid_entry *ueident;
0880         u16 v2_ext_offset;
0881 
0882         v2_ext->hdr.flag.release = SMC_RELEASE;
0883         v2_ext_offset = sizeof(*pclc_smcd) -
0884             offsetofend(struct smc_clc_msg_smcd, v2_ext_offset);
0885         if (ini->smc_type_v1 != SMC_TYPE_N)
0886             v2_ext_offset += sizeof(*pclc_prfx) +
0887                         pclc_prfx->ipv6_prefixes_cnt *
0888                         sizeof(ipv6_prfx[0]);
0889         pclc_smcd->v2_ext_offset = htons(v2_ext_offset);
0890         plen += sizeof(*v2_ext);
0891 
0892         read_lock(&smc_clc_eid_table.lock);
0893         v2_ext->hdr.eid_cnt = smc_clc_eid_table.ueid_cnt;
0894         plen += smc_clc_eid_table.ueid_cnt * SMC_MAX_EID_LEN;
0895         i = 0;
0896         list_for_each_entry(ueident, &smc_clc_eid_table.list, list) {
0897             memcpy(v2_ext->user_eids[i++], ueident->eid,
0898                    sizeof(ueident->eid));
0899         }
0900         read_unlock(&smc_clc_eid_table.lock);
0901     }
0902     if (smcd_indicated(ini->smc_type_v2)) {
0903         u8 *eid = NULL;
0904 
0905         v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled;
0906         v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt;
0907         v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) -
0908                 offsetofend(struct smc_clnt_opts_area_hdr,
0909                         smcd_v2_ext_offset) +
0910                 v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN);
0911         smc_ism_get_system_eid(&eid);
0912         if (eid && v2_ext->hdr.flag.seid)
0913             memcpy(smcd_v2_ext->system_eid, eid, SMC_MAX_EID_LEN);
0914         plen += sizeof(*smcd_v2_ext);
0915         if (ini->ism_offered_cnt) {
0916             for (i = 1; i <= ini->ism_offered_cnt; i++) {
0917                 gidchids[i - 1].gid =
0918                     htonll(ini->ism_dev[i]->local_gid);
0919                 gidchids[i - 1].chid =
0920                     htons(smc_ism_get_chid(ini->ism_dev[i]));
0921             }
0922             plen += ini->ism_offered_cnt *
0923                 sizeof(struct smc_clc_smcd_gid_chid);
0924         }
0925     }
0926     if (smcr_indicated(ini->smc_type_v2))
0927         memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
0928 
0929     pclc_base->hdr.length = htons(plen);
0930     memcpy(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
0931 
0932     /* send SMC Proposal CLC message */
0933     memset(&msg, 0, sizeof(msg));
0934     i = 0;
0935     vec[i].iov_base = pclc_base;
0936     vec[i++].iov_len = sizeof(*pclc_base);
0937     vec[i].iov_base = pclc_smcd;
0938     vec[i++].iov_len = sizeof(*pclc_smcd);
0939     if (ini->smc_type_v1 != SMC_TYPE_N) {
0940         vec[i].iov_base = pclc_prfx;
0941         vec[i++].iov_len = sizeof(*pclc_prfx);
0942         if (pclc_prfx->ipv6_prefixes_cnt > 0) {
0943             vec[i].iov_base = ipv6_prfx;
0944             vec[i++].iov_len = pclc_prfx->ipv6_prefixes_cnt *
0945                        sizeof(ipv6_prfx[0]);
0946         }
0947     }
0948     if (ini->smc_type_v2 != SMC_TYPE_N) {
0949         vec[i].iov_base = v2_ext;
0950         vec[i++].iov_len = sizeof(*v2_ext) +
0951                    (v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN);
0952         if (smcd_indicated(ini->smc_type_v2)) {
0953             vec[i].iov_base = smcd_v2_ext;
0954             vec[i++].iov_len = sizeof(*smcd_v2_ext);
0955             if (ini->ism_offered_cnt) {
0956                 vec[i].iov_base = gidchids;
0957                 vec[i++].iov_len = ini->ism_offered_cnt *
0958                     sizeof(struct smc_clc_smcd_gid_chid);
0959             }
0960         }
0961     }
0962     vec[i].iov_base = trl;
0963     vec[i++].iov_len = sizeof(*trl);
0964     /* due to the few bytes needed for clc-handshake this cannot block */
0965     len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
0966     if (len < 0) {
0967         smc->sk.sk_err = smc->clcsock->sk->sk_err;
0968         reason_code = -smc->sk.sk_err;
0969     } else if (len < ntohs(pclc_base->hdr.length)) {
0970         reason_code = -ENETUNREACH;
0971         smc->sk.sk_err = -reason_code;
0972     }
0973 
0974     kfree(pclc);
0975     return reason_code;
0976 }
0977 
0978 /* build and send CLC CONFIRM / ACCEPT message */
0979 static int smc_clc_send_confirm_accept(struct smc_sock *smc,
0980                        struct smc_clc_msg_accept_confirm_v2 *clc_v2,
0981                        int first_contact, u8 version,
0982                        u8 *eid, struct smc_init_info *ini)
0983 {
0984     struct smc_connection *conn = &smc->conn;
0985     struct smc_clc_msg_accept_confirm *clc;
0986     struct smc_clc_first_contact_ext fce;
0987     struct smc_clc_fce_gid_ext gle;
0988     struct smc_clc_msg_trail trl;
0989     struct kvec vec[5];
0990     struct msghdr msg;
0991     int i, len;
0992 
0993     /* send SMC Confirm CLC msg */
0994     clc = (struct smc_clc_msg_accept_confirm *)clc_v2;
0995     clc->hdr.version = version; /* SMC version */
0996     if (first_contact)
0997         clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK;
0998     if (conn->lgr->is_smcd) {
0999         /* 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[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 = conn->rmb_desc->is_vm ?
1050             cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) :
1051             cpu_to_be64((u64)sg_dma_address
1052                     (conn->rmb_desc->sgt[link->link_idx].sgl));
1053         hton24(clc->r0.psn, link->psn_initial);
1054         if (version == SMC_V1) {
1055             clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
1056         } else {
1057             if (eid && eid[0])
1058                 memcpy(clc_v2->r1.eid, eid, SMC_MAX_EID_LEN);
1059             len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2;
1060             if (first_contact) {
1061                 smc_clc_fill_fce(&fce, &len);
1062                 fce.v2_direct = !link->lgr->uses_gateway;
1063                 memset(&gle, 0, sizeof(gle));
1064                 if (ini && clc->hdr.type == SMC_CLC_CONFIRM) {
1065                     gle.gid_cnt = ini->smcrv2.gidlist.len;
1066                     len += sizeof(gle);
1067                     len += gle.gid_cnt * sizeof(gle.gid[0]);
1068                 } else {
1069                     len += sizeof(gle.reserved);
1070                 }
1071             }
1072             clc_v2->hdr.length = htons(len);
1073         }
1074         memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
1075     }
1076 
1077     memset(&msg, 0, sizeof(msg));
1078     i = 0;
1079     vec[i].iov_base = clc_v2;
1080     if (version > SMC_V1)
1081         vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
1082                     SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 :
1083                     SMCR_CLC_ACCEPT_CONFIRM_LEN_V2) -
1084                    sizeof(trl);
1085     else
1086         vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
1087                         SMCD_CLC_ACCEPT_CONFIRM_LEN :
1088                         SMCR_CLC_ACCEPT_CONFIRM_LEN) -
1089                    sizeof(trl);
1090     if (version > SMC_V1 && first_contact) {
1091         vec[i].iov_base = &fce;
1092         vec[i++].iov_len = sizeof(fce);
1093         if (!conn->lgr->is_smcd) {
1094             if (clc->hdr.type == SMC_CLC_CONFIRM) {
1095                 vec[i].iov_base = &gle;
1096                 vec[i++].iov_len = sizeof(gle);
1097                 vec[i].iov_base = &ini->smcrv2.gidlist.list;
1098                 vec[i++].iov_len = gle.gid_cnt *
1099                            sizeof(gle.gid[0]);
1100             } else {
1101                 vec[i].iov_base = &gle.reserved;
1102                 vec[i++].iov_len = sizeof(gle.reserved);
1103             }
1104         }
1105     }
1106     vec[i].iov_base = &trl;
1107     vec[i++].iov_len = sizeof(trl);
1108     return kernel_sendmsg(smc->clcsock, &msg, vec, 1,
1109                   ntohs(clc->hdr.length));
1110 }
1111 
1112 /* send CLC CONFIRM message across internal TCP socket */
1113 int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
1114              u8 version, u8 *eid, struct smc_init_info *ini)
1115 {
1116     struct smc_clc_msg_accept_confirm_v2 cclc_v2;
1117     int reason_code = 0;
1118     int len;
1119 
1120     /* send SMC Confirm CLC msg */
1121     memset(&cclc_v2, 0, sizeof(cclc_v2));
1122     cclc_v2.hdr.type = SMC_CLC_CONFIRM;
1123     len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact,
1124                       version, eid, ini);
1125     if (len < ntohs(cclc_v2.hdr.length)) {
1126         if (len >= 0) {
1127             reason_code = -ENETUNREACH;
1128             smc->sk.sk_err = -reason_code;
1129         } else {
1130             smc->sk.sk_err = smc->clcsock->sk->sk_err;
1131             reason_code = -smc->sk.sk_err;
1132         }
1133     }
1134     return reason_code;
1135 }
1136 
1137 /* send CLC ACCEPT message across internal TCP socket */
1138 int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact,
1139             u8 version, u8 *negotiated_eid)
1140 {
1141     struct smc_clc_msg_accept_confirm_v2 aclc_v2;
1142     int len;
1143 
1144     memset(&aclc_v2, 0, sizeof(aclc_v2));
1145     aclc_v2.hdr.type = SMC_CLC_ACCEPT;
1146     len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact,
1147                       version, negotiated_eid, NULL);
1148     if (len < ntohs(aclc_v2.hdr.length))
1149         len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
1150 
1151     return len > 0 ? 0 : len;
1152 }
1153 
1154 void smc_clc_get_hostname(u8 **host)
1155 {
1156     *host = &smc_hostname[0];
1157 }
1158 
1159 void __init smc_clc_init(void)
1160 {
1161     struct new_utsname *u;
1162 
1163     memset(smc_hostname, _S, sizeof(smc_hostname)); /* ASCII blanks */
1164     u = utsname();
1165     memcpy(smc_hostname, u->nodename,
1166            min_t(size_t, strlen(u->nodename), sizeof(smc_hostname)));
1167 
1168     INIT_LIST_HEAD(&smc_clc_eid_table.list);
1169     rwlock_init(&smc_clc_eid_table.lock);
1170     smc_clc_eid_table.ueid_cnt = 0;
1171     smc_clc_eid_table.seid_enabled = 1;
1172 }
1173 
1174 void smc_clc_exit(void)
1175 {
1176     smc_clc_ueid_remove(NULL);
1177 }