Jeff Layton | 6c37f0e | 2019-06-03 14:45:16 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | |
| 3 | #include <linux/ceph/decode.h> |
| 4 | |
| 5 | static int |
| 6 | ceph_decode_entity_addr_versioned(void **p, void *end, |
| 7 | struct ceph_entity_addr *addr) |
| 8 | { |
| 9 | int ret; |
| 10 | u8 struct_v; |
| 11 | u32 struct_len, addr_len; |
| 12 | void *struct_end; |
| 13 | |
| 14 | ret = ceph_start_decoding(p, end, 1, "entity_addr_t", &struct_v, |
| 15 | &struct_len); |
| 16 | if (ret) |
| 17 | goto bad; |
| 18 | |
| 19 | ret = -EINVAL; |
| 20 | struct_end = *p + struct_len; |
| 21 | |
| 22 | ceph_decode_copy_safe(p, end, &addr->type, sizeof(addr->type), bad); |
| 23 | |
Jeff Layton | 6c37f0e | 2019-06-03 14:45:16 -0400 | [diff] [blame] | 24 | ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); |
| 25 | |
| 26 | ceph_decode_32_safe(p, end, addr_len, bad); |
| 27 | if (addr_len > sizeof(addr->in_addr)) |
| 28 | goto bad; |
| 29 | |
| 30 | memset(&addr->in_addr, 0, sizeof(addr->in_addr)); |
| 31 | if (addr_len) { |
| 32 | ceph_decode_copy_safe(p, end, &addr->in_addr, addr_len, bad); |
| 33 | |
| 34 | addr->in_addr.ss_family = |
| 35 | le16_to_cpu((__force __le16)addr->in_addr.ss_family); |
| 36 | } |
| 37 | |
| 38 | /* Advance past anything the client doesn't yet understand */ |
| 39 | *p = struct_end; |
| 40 | ret = 0; |
| 41 | bad: |
| 42 | return ret; |
| 43 | } |
| 44 | |
| 45 | static int |
| 46 | ceph_decode_entity_addr_legacy(void **p, void *end, |
| 47 | struct ceph_entity_addr *addr) |
| 48 | { |
| 49 | int ret = -EINVAL; |
| 50 | |
| 51 | /* Skip rest of type field */ |
| 52 | ceph_decode_skip_n(p, end, 3, bad); |
Jeff Layton | d3c3c0a | 2019-06-17 06:57:25 -0400 | [diff] [blame] | 53 | |
| 54 | /* |
| 55 | * Clients that don't support ADDR2 always send TYPE_NONE, change it |
| 56 | * to TYPE_LEGACY for forward compatibility. |
| 57 | */ |
| 58 | addr->type = CEPH_ENTITY_ADDR_TYPE_LEGACY; |
Jeff Layton | 6c37f0e | 2019-06-03 14:45:16 -0400 | [diff] [blame] | 59 | ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); |
| 60 | memset(&addr->in_addr, 0, sizeof(addr->in_addr)); |
| 61 | ceph_decode_copy_safe(p, end, &addr->in_addr, |
| 62 | sizeof(addr->in_addr), bad); |
| 63 | addr->in_addr.ss_family = |
| 64 | be16_to_cpu((__force __be16)addr->in_addr.ss_family); |
| 65 | ret = 0; |
| 66 | bad: |
| 67 | return ret; |
| 68 | } |
| 69 | |
| 70 | int |
| 71 | ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr) |
| 72 | { |
| 73 | u8 marker; |
| 74 | |
| 75 | ceph_decode_8_safe(p, end, marker, bad); |
| 76 | if (marker == 1) |
| 77 | return ceph_decode_entity_addr_versioned(p, end, addr); |
| 78 | else if (marker == 0) |
| 79 | return ceph_decode_entity_addr_legacy(p, end, addr); |
| 80 | bad: |
| 81 | return -EINVAL; |
| 82 | } |
| 83 | EXPORT_SYMBOL(ceph_decode_entity_addr); |
| 84 | |