Merge branch 'work.dcache2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / net / ceph / decode.c
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
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);
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;
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