Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/ceph/ceph_debug.h>
0003 
0004 #include <linux/inet.h>
0005 
0006 #include <linux/ceph/decode.h>
0007 #include <linux/ceph/messenger.h>  /* for ceph_pr_addr() */
0008 
0009 static int
0010 ceph_decode_entity_addr_versioned(void **p, void *end,
0011                   struct ceph_entity_addr *addr)
0012 {
0013     int ret;
0014     u8 struct_v;
0015     u32 struct_len, addr_len;
0016     void *struct_end;
0017 
0018     ret = ceph_start_decoding(p, end, 1, "entity_addr_t", &struct_v,
0019                   &struct_len);
0020     if (ret)
0021         goto bad;
0022 
0023     ret = -EINVAL;
0024     struct_end = *p + struct_len;
0025 
0026     ceph_decode_copy_safe(p, end, &addr->type, sizeof(addr->type), bad);
0027 
0028     ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad);
0029 
0030     ceph_decode_32_safe(p, end, addr_len, bad);
0031     if (addr_len > sizeof(addr->in_addr))
0032         goto bad;
0033 
0034     memset(&addr->in_addr, 0, sizeof(addr->in_addr));
0035     if (addr_len) {
0036         ceph_decode_copy_safe(p, end, &addr->in_addr, addr_len, bad);
0037 
0038         addr->in_addr.ss_family =
0039             le16_to_cpu((__force __le16)addr->in_addr.ss_family);
0040     }
0041 
0042     /* Advance past anything the client doesn't yet understand */
0043     *p = struct_end;
0044     ret = 0;
0045 bad:
0046     return ret;
0047 }
0048 
0049 static int
0050 ceph_decode_entity_addr_legacy(void **p, void *end,
0051                    struct ceph_entity_addr *addr)
0052 {
0053     int ret = -EINVAL;
0054 
0055     /* Skip rest of type field */
0056     ceph_decode_skip_n(p, end, 3, bad);
0057 
0058     /*
0059      * Clients that don't support ADDR2 always send TYPE_NONE, change it
0060      * to TYPE_LEGACY for forward compatibility.
0061      */
0062     addr->type = CEPH_ENTITY_ADDR_TYPE_LEGACY;
0063     ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad);
0064     memset(&addr->in_addr, 0, sizeof(addr->in_addr));
0065     ceph_decode_copy_safe(p, end, &addr->in_addr,
0066                   sizeof(addr->in_addr), bad);
0067     addr->in_addr.ss_family =
0068             be16_to_cpu((__force __be16)addr->in_addr.ss_family);
0069     ret = 0;
0070 bad:
0071     return ret;
0072 }
0073 
0074 int
0075 ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr)
0076 {
0077     u8 marker;
0078 
0079     ceph_decode_8_safe(p, end, marker, bad);
0080     if (marker == 1)
0081         return ceph_decode_entity_addr_versioned(p, end, addr);
0082     else if (marker == 0)
0083         return ceph_decode_entity_addr_legacy(p, end, addr);
0084 bad:
0085     return -EINVAL;
0086 }
0087 EXPORT_SYMBOL(ceph_decode_entity_addr);
0088 
0089 /*
0090  * Return addr of desired type (MSGR2 or LEGACY) or error.
0091  * Make sure there is only one match.
0092  *
0093  * Assume encoding with MSG_ADDR2.
0094  */
0095 int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2,
0096                    struct ceph_entity_addr *addr)
0097 {
0098     __le32 my_type = msgr2 ? CEPH_ENTITY_ADDR_TYPE_MSGR2 :
0099                  CEPH_ENTITY_ADDR_TYPE_LEGACY;
0100     struct ceph_entity_addr tmp_addr;
0101     int addr_cnt;
0102     bool found;
0103     u8 marker;
0104     int ret;
0105     int i;
0106 
0107     ceph_decode_8_safe(p, end, marker, e_inval);
0108     if (marker != 2) {
0109         pr_err("bad addrvec marker %d\n", marker);
0110         return -EINVAL;
0111     }
0112 
0113     ceph_decode_32_safe(p, end, addr_cnt, e_inval);
0114     dout("%s addr_cnt %d\n", __func__, addr_cnt);
0115 
0116     found = false;
0117     for (i = 0; i < addr_cnt; i++) {
0118         ret = ceph_decode_entity_addr(p, end, &tmp_addr);
0119         if (ret)
0120             return ret;
0121 
0122         dout("%s i %d addr %s\n", __func__, i, ceph_pr_addr(&tmp_addr));
0123         if (tmp_addr.type == my_type) {
0124             if (found) {
0125                 pr_err("another match of type %d in addrvec\n",
0126                        le32_to_cpu(my_type));
0127                 return -EINVAL;
0128             }
0129 
0130             memcpy(addr, &tmp_addr, sizeof(*addr));
0131             found = true;
0132         }
0133     }
0134 
0135     if (found)
0136         return 0;
0137 
0138     if (!addr_cnt)
0139         return 0;  /* normal -- e.g. unused OSD id/slot */
0140 
0141     if (addr_cnt == 1 && !memchr_inv(&tmp_addr, 0, sizeof(tmp_addr)))
0142         return 0;  /* weird but effectively the same as !addr_cnt */
0143 
0144     pr_err("no match of type %d in addrvec\n", le32_to_cpu(my_type));
0145     return -ENOENT;
0146 
0147 e_inval:
0148     return -EINVAL;
0149 }
0150 EXPORT_SYMBOL(ceph_decode_entity_addrvec);
0151 
0152 static int get_sockaddr_encoding_len(sa_family_t family)
0153 {
0154     union {
0155         struct sockaddr sa;
0156         struct sockaddr_in sin;
0157         struct sockaddr_in6 sin6;
0158     } u;
0159 
0160     switch (family) {
0161     case AF_INET:
0162         return sizeof(u.sin);
0163     case AF_INET6:
0164         return sizeof(u.sin6);
0165     default:
0166         return sizeof(u);
0167     }
0168 }
0169 
0170 int ceph_entity_addr_encoding_len(const struct ceph_entity_addr *addr)
0171 {
0172     sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
0173     int addr_len = get_sockaddr_encoding_len(family);
0174 
0175     return 1 + CEPH_ENCODING_START_BLK_LEN + 4 + 4 + 4 + addr_len;
0176 }
0177 
0178 void ceph_encode_entity_addr(void **p, const struct ceph_entity_addr *addr)
0179 {
0180     sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
0181     int addr_len = get_sockaddr_encoding_len(family);
0182 
0183     ceph_encode_8(p, 1);  /* marker */
0184     ceph_start_encoding(p, 1, 1, sizeof(addr->type) +
0185                      sizeof(addr->nonce) +
0186                      sizeof(u32) + addr_len);
0187     ceph_encode_copy(p, &addr->type, sizeof(addr->type));
0188     ceph_encode_copy(p, &addr->nonce, sizeof(addr->nonce));
0189 
0190     ceph_encode_32(p, addr_len);
0191     ceph_encode_16(p, family);
0192     ceph_encode_copy(p, addr->in_addr.__data, addr_len - sizeof(family));
0193 }