blob: aa79fe3f168b1bb60964be2a02ec8a08bb76d2ac [file] [log] [blame]
David Howellsec268152007-04-26 15:49:28 -07001/* AFS Volume Location Service client
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/gfp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/init.h>
14#include <linux/sched.h>
David Howells4d9df982017-11-02 15:27:47 +000015#include "afs_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include "internal.h"
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018/*
David Howells08e0e7c2007-04-26 15:55:03 -070019 * deliver reply data to a VL.GetEntryByXXX call
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
David Howellsd0016482016-08-30 20:42:14 +010021static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -070022{
David Howells08e0e7c2007-04-26 15:55:03 -070023 struct afs_cache_vlocation *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 __be32 *bp;
David Howells08e0e7c2007-04-26 15:55:03 -070025 u32 tmp;
David Howells372ee162016-08-03 14:11:40 +010026 int loop, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
David Howellsd0016482016-08-30 20:42:14 +010028 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
David Howellsd0016482016-08-30 20:42:14 +010030 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +010031 if (ret < 0)
32 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
David Howells08e0e7c2007-04-26 15:55:03 -070034 /* unmarshall the reply once we've received all of it */
David Howells97e30432017-11-02 15:27:48 +000035 entry = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -070036 bp = call->buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
David Howells08e0e7c2007-04-26 15:55:03 -070038 for (loop = 0; loop < 64; loop++)
39 entry->name[loop] = ntohl(*bp++);
40 entry->name[loop] = 0;
41 bp++; /* final NUL */
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
David Howells08e0e7c2007-04-26 15:55:03 -070043 bp++; /* type */
44 entry->nservers = ntohl(*bp++);
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
David Howells4d9df982017-11-02 15:27:47 +000046 for (loop = 0; loop < 8; loop++) {
47 entry->servers[loop].srx_family = AF_RXRPC;
48 entry->servers[loop].srx_service = FS_SERVICE;
49 entry->servers[loop].transport_type = SOCK_DGRAM;
David Howells3838d3e2017-11-02 15:27:47 +000050 entry->servers[loop].transport_len = sizeof(entry->servers[loop].transport.sin6);
51 entry->servers[loop].transport.sin6.sin6_family = AF_INET6;
52 entry->servers[loop].transport.sin6.sin6_port = htons(AFS_FS_PORT);
53 entry->servers[loop].transport.sin6.sin6_flowinfo = 0;
54 entry->servers[loop].transport.sin6.sin6_scope_id = 0;
55 entry->servers[loop].transport.sin6.sin6_addr.s6_addr32[0] = 0;
56 entry->servers[loop].transport.sin6.sin6_addr.s6_addr32[1] = 0;
57 entry->servers[loop].transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
58 entry->servers[loop].transport.sin6.sin6_addr.s6_addr32[3] = *bp++;
David Howells4d9df982017-11-02 15:27:47 +000059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
David Howells08e0e7c2007-04-26 15:55:03 -070061 bp += 8; /* partition IDs */
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
David Howells08e0e7c2007-04-26 15:55:03 -070063 for (loop = 0; loop < 8; loop++) {
64 tmp = ntohl(*bp++);
65 entry->srvtmask[loop] = 0;
66 if (tmp & AFS_VLSF_RWVOL)
67 entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
68 if (tmp & AFS_VLSF_ROVOL)
69 entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
70 if (tmp & AFS_VLSF_BACKVOL)
71 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 }
73
David Howells08e0e7c2007-04-26 15:55:03 -070074 entry->vid[0] = ntohl(*bp++);
75 entry->vid[1] = ntohl(*bp++);
76 entry->vid[2] = ntohl(*bp++);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
David Howells08e0e7c2007-04-26 15:55:03 -070078 bp++; /* clone ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
David Howells08e0e7c2007-04-26 15:55:03 -070080 tmp = ntohl(*bp++); /* flags */
81 entry->vidmask = 0;
82 if (tmp & AFS_VLF_RWEXISTS)
83 entry->vidmask |= AFS_VOL_VTM_RW;
84 if (tmp & AFS_VLF_ROEXISTS)
85 entry->vidmask |= AFS_VOL_VTM_RO;
86 if (tmp & AFS_VLF_BACKEXISTS)
87 entry->vidmask |= AFS_VOL_VTM_BAK;
88 if (!entry->vidmask)
89 return -EBADMSG;
90
91 _leave(" = 0 [done]");
92 return 0;
David Howellsec268152007-04-26 15:49:28 -070093}
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Linus Torvalds1da177e2005-04-16 15:20:36 -070095/*
David Howells08e0e7c2007-04-26 15:55:03 -070096 * VL.GetEntryByName operation type
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 */
David Howells08e0e7c2007-04-26 15:55:03 -070098static const struct afs_call_type afs_RXVLGetEntryByName = {
David Howells00d3b7a2007-04-26 15:57:07 -070099 .name = "VL.GetEntryByName",
David Howells08e0e7c2007-04-26 15:55:03 -0700100 .deliver = afs_deliver_vl_get_entry_by_xxx,
David Howells08e0e7c2007-04-26 15:55:03 -0700101 .destructor = afs_flat_call_destructor,
102};
103
104/*
105 * VL.GetEntryById operation type
106 */
107static const struct afs_call_type afs_RXVLGetEntryById = {
David Howells00d3b7a2007-04-26 15:57:07 -0700108 .name = "VL.GetEntryById",
David Howells08e0e7c2007-04-26 15:55:03 -0700109 .deliver = afs_deliver_vl_get_entry_by_xxx,
David Howells08e0e7c2007-04-26 15:55:03 -0700110 .destructor = afs_flat_call_destructor,
111};
112
113/*
114 * dispatch a get volume entry by name operation
115 */
David Howellsf044c882017-11-02 15:27:45 +0000116int afs_vl_get_entry_by_name(struct afs_net *net,
David Howells4d9df982017-11-02 15:27:47 +0000117 struct sockaddr_rxrpc *addr,
David Howells00d3b7a2007-04-26 15:57:07 -0700118 struct key *key,
David Howells08e0e7c2007-04-26 15:55:03 -0700119 const char *volname,
120 struct afs_cache_vlocation *entry,
David Howells56ff9c82017-01-05 10:38:36 +0000121 bool async)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122{
David Howells08e0e7c2007-04-26 15:55:03 -0700123 struct afs_call *call;
124 size_t volnamesz, reqsz, padsz;
125 __be32 *bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
David Howells08e0e7c2007-04-26 15:55:03 -0700127 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
David Howells08e0e7c2007-04-26 15:55:03 -0700129 volnamesz = strlen(volname);
130 padsz = (4 - (volnamesz & 3)) & 3;
131 reqsz = 8 + volnamesz + padsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
David Howellsf044c882017-11-02 15:27:45 +0000133 call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByName, reqsz, 384);
David Howells08e0e7c2007-04-26 15:55:03 -0700134 if (!call)
135 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
David Howells00d3b7a2007-04-26 15:57:07 -0700137 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000138 call->reply[0] = entry;
David Howells08e0e7c2007-04-26 15:55:03 -0700139
140 /* marshall the parameters */
141 bp = call->request;
142 *bp++ = htonl(VLGETENTRYBYNAME);
143 *bp++ = htonl(volnamesz);
144 memcpy(bp, volname, volnamesz);
145 if (padsz > 0)
146 memset((void *) bp + volnamesz, 0, padsz);
147
148 /* initiate the call */
David Howells56ff9c82017-01-05 10:38:36 +0000149 return afs_make_call(addr, call, GFP_KERNEL, async);
David Howellsec268152007-04-26 15:49:28 -0700150}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152/*
David Howells08e0e7c2007-04-26 15:55:03 -0700153 * dispatch a get volume entry by ID operation
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 */
David Howellsf044c882017-11-02 15:27:45 +0000155int afs_vl_get_entry_by_id(struct afs_net *net,
David Howells4d9df982017-11-02 15:27:47 +0000156 struct sockaddr_rxrpc *addr,
David Howells00d3b7a2007-04-26 15:57:07 -0700157 struct key *key,
David Howells08e0e7c2007-04-26 15:55:03 -0700158 afs_volid_t volid,
159 afs_voltype_t voltype,
160 struct afs_cache_vlocation *entry,
David Howells56ff9c82017-01-05 10:38:36 +0000161 bool async)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
David Howells08e0e7c2007-04-26 15:55:03 -0700163 struct afs_call *call;
164 __be32 *bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
David Howells08e0e7c2007-04-26 15:55:03 -0700166 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
David Howellsf044c882017-11-02 15:27:45 +0000168 call = afs_alloc_flat_call(net, &afs_RXVLGetEntryById, 12, 384);
David Howells08e0e7c2007-04-26 15:55:03 -0700169 if (!call)
170 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
David Howells00d3b7a2007-04-26 15:57:07 -0700172 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000173 call->reply[0] = entry;
David Howells08e0e7c2007-04-26 15:55:03 -0700174
175 /* marshall the parameters */
176 bp = call->request;
177 *bp++ = htonl(VLGETENTRYBYID);
178 *bp++ = htonl(volid);
179 *bp = htonl(voltype);
180
181 /* initiate the call */
David Howells56ff9c82017-01-05 10:38:36 +0000182 return afs_make_call(addr, call, GFP_KERNEL, async);
David Howellsec268152007-04-26 15:49:28 -0700183}