0001
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
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
0056 ceph_decode_skip_n(p, end, 3, bad);
0057
0058
0059
0060
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
0091
0092
0093
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;
0140
0141 if (addr_cnt == 1 && !memchr_inv(&tmp_addr, 0, sizeof(tmp_addr)))
0142 return 0;
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);
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 }