1/*
2 * include/linux/nfsd/nfsfh.h
3 *
4 * This file describes the layout of the file handles as passed
5 * over the wire.
6 *
7 * Earlier versions of knfsd used to sign file handles using keyed MD5
8 * or SHA. I've removed this code, because it doesn't give you more
9 * security than blocking external access to port 2049 on your firewall.
10 *
11 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
12 */
13
14#ifndef _LINUX_NFSD_FH_H
15#define _LINUX_NFSD_FH_H
16
17#include <asm/types.h>
18#ifdef __KERNEL__
19# include <linux/types.h>
20# include <linux/string.h>
21# include <linux/fs.h>
22#endif
23#include <linux/nfsd/const.h>
24#include <linux/nfsd/debug.h>
25
26/*
27 * This is the old "dentry style" Linux NFSv2 file handle.
28 *
29 * The xino and xdev fields are currently used to transport the
30 * ino/dev of the exported inode.
31 */
32struct nfs_fhbase_old {
33	__u32		fb_dcookie;	/* dentry cookie - always 0xfeebbaca */
34	__u32		fb_ino;		/* our inode number */
35	__u32		fb_dirino;	/* dir inode number, 0 for directories */
36	__u32		fb_dev;		/* our device */
37	__u32		fb_xdev;
38	__u32		fb_xino;
39	__u32		fb_generation;
40};
41
42/*
43 * This is the new flexible, extensible style NFSv2/v3 file handle.
44 * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
45 *
46 * The file handle is seens as a list of 4byte words.
47 * The first word contains a version number (1) and four descriptor bytes
48 * that tell how the remaining 3 variable length fields should be handled.
49 * These three bytes are auth_type, fsid_type and fileid_type.
50 *
51 * All 4byte values are in host-byte-order.
52 *
53 * The auth_type field specifies how the filehandle can be authenticated
54 * This might allow a file to be confirmed to be in a writable part of a
55 * filetree without checking the path from it upto the root.
56 * Current values:
57 *     0  - No authentication.  fb_auth is 0 bytes long
58 * Possible future values:
59 *     1  - 4 bytes taken from MD5 hash of the remainer of the file handle
60 *          prefixed by a secret and with the important export flags.
61 *
62 * The fsid_type identifies how the filesystem (or export point) is
63 *    encoded.
64 *  Current values:
65 *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
66 *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
67 *              says we mustn't.  We must break it up and reassemble.
68 *     1  - 4 byte user specified identifier
69 *     2  - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
70 *     3  - 4 byte device id, encoded for user-space, 4 byte inode number
71 *
72 * The fileid_type identified how the file within the filesystem is encoded.
73 * This is (will be) passed to, and set by, the underlying filesystem if it supports
74 * filehandle operations.  The filesystem must not use the value '0' or '0xff' and may
75 * only use the values 1 and 2 as defined below:
76 *  Current values:
77 *    0   - The root, or export point, of the filesystem.  fb_fileid is 0 bytes.
78 *    1   - 32bit inode number, 32 bit generation number.
79 *    2   - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
80 *
81 */
82struct nfs_fhbase_new {
83	__u8		fb_version;	/* == 1, even => nfs_fhbase_old */
84	__u8		fb_auth_type;
85	__u8		fb_fsid_type;
86	__u8		fb_fileid_type;
87	__u32		fb_auth[1];
88/*	__u32		fb_fsid[0]; floating */
89/*	__u32		fb_fileid[0]; floating */
90};
91
92struct knfsd_fh {
93	unsigned int	fh_size;	/* significant for NFSv3.
94					 * Points to the current size while building
95					 * a new file handle
96					 */
97	union {
98		struct nfs_fhbase_old	fh_old;
99		__u32			fh_pad[NFS4_FHSIZE/4];
100		struct nfs_fhbase_new	fh_new;
101	} fh_base;
102};
103
104#define ofh_dcookie		fh_base.fh_old.fb_dcookie
105#define ofh_ino			fh_base.fh_old.fb_ino
106#define ofh_dirino		fh_base.fh_old.fb_dirino
107#define ofh_dev			fh_base.fh_old.fb_dev
108#define ofh_xdev		fh_base.fh_old.fb_xdev
109#define ofh_xino		fh_base.fh_old.fb_xino
110#define ofh_generation		fh_base.fh_old.fb_generation
111
112#define	fh_version		fh_base.fh_new.fb_version
113#define	fh_fsid_type		fh_base.fh_new.fb_fsid_type
114#define	fh_auth_type		fh_base.fh_new.fb_auth_type
115#define	fh_fileid_type		fh_base.fh_new.fb_fileid_type
116#define	fh_auth			fh_base.fh_new.fb_auth
117#define	fh_fsid			fh_base.fh_new.fb_auth
118
119#ifdef __KERNEL__
120
121static inline __u32 ino_t_to_u32(ino_t ino)
122{
123	return (__u32) ino;
124}
125
126static inline ino_t u32_to_ino_t(__u32 uino)
127{
128	return (ino_t) uino;
129}
130
131/*
132 * This is the internal representation of an NFS handle used in knfsd.
133 * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
134 */
135typedef struct svc_fh {
136	struct knfsd_fh		fh_handle;	/* FH data */
137	struct dentry *		fh_dentry;	/* validated dentry */
138	struct svc_export *	fh_export;	/* export pointer */
139	int			fh_maxsize;	/* max size for fh_handle */
140
141	unsigned char		fh_locked;	/* inode locked by us */
142
143#ifdef CONFIG_NFSD_V3
144	unsigned char		fh_post_saved;	/* post-op attrs saved */
145	unsigned char		fh_pre_saved;	/* pre-op attrs saved */
146
147	/* Pre-op attributes saved during fh_lock */
148	__u64			fh_pre_size;	/* size before operation */
149	struct timespec		fh_pre_mtime;	/* mtime before oper */
150	struct timespec		fh_pre_ctime;	/* ctime before oper */
151
152	/* Post-op attributes saved in fh_unlock */
153	umode_t			fh_post_mode;	/* i_mode */
154	nlink_t			fh_post_nlink;	/* i_nlink */
155	uid_t			fh_post_uid;	/* i_uid */
156	gid_t			fh_post_gid;	/* i_gid */
157	__u64			fh_post_size;	/* i_size */
158	unsigned long		fh_post_blocks; /* i_blocks */
159	unsigned long		fh_post_blksize;/* i_blksize */
160	__u32			fh_post_rdev[2];/* i_rdev */
161	struct timespec		fh_post_atime;	/* i_atime */
162	struct timespec		fh_post_mtime;	/* i_mtime */
163	struct timespec		fh_post_ctime;	/* i_ctime */
164#endif /* CONFIG_NFSD_V3 */
165
166} svc_fh;
167
168static inline void mk_fsid_v0(u32 *fsidv, dev_t dev, ino_t ino)
169{
170	fsidv[0] = htonl((MAJOR(dev)<<16) |
171			MINOR(dev));
172	fsidv[1] = ino_t_to_u32(ino);
173}
174
175static inline void mk_fsid_v1(u32 *fsidv, u32 fsid)
176{
177	fsidv[0] = fsid;
178}
179
180static inline void mk_fsid_v2(u32 *fsidv, dev_t dev, ino_t ino)
181{
182	fsidv[0] = htonl(MAJOR(dev));
183	fsidv[1] = htonl(MINOR(dev));
184	fsidv[2] = ino_t_to_u32(ino);
185}
186
187static inline void mk_fsid_v3(u32 *fsidv, dev_t dev, ino_t ino)
188{
189	fsidv[0] = new_encode_dev(dev);
190	fsidv[1] = ino_t_to_u32(ino);
191}
192
193static inline int key_len(int type)
194{
195	switch(type) {
196	case 0: return 8;
197	case 1: return 4;
198	case 2: return 12;
199	case 3: return 8;
200	default: return 0;
201	}
202}
203
204/*
205 * Shorthand for dprintk()'s
206 */
207extern char * SVCFH_fmt(struct svc_fh *fhp);
208
209/*
210 * Function prototypes
211 */
212u32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
213int	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
214int	fh_update(struct svc_fh *);
215void	fh_put(struct svc_fh *);
216
217static __inline__ struct svc_fh *
218fh_copy(struct svc_fh *dst, struct svc_fh *src)
219{
220	if (src->fh_dentry || src->fh_locked) {
221		struct dentry *dentry = src->fh_dentry;
222		printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n",
223			dentry->d_parent->d_name.name, dentry->d_name.name);
224	}
225
226	*dst = *src;
227	return dst;
228}
229
230static __inline__ struct svc_fh *
231fh_init(struct svc_fh *fhp, int maxsize)
232{
233	memset(fhp, 0, sizeof(*fhp));
234	fhp->fh_maxsize = maxsize;
235	return fhp;
236}
237
238#ifdef CONFIG_NFSD_V3
239/*
240 * Fill in the pre_op attr for the wcc data
241 */
242static inline void
243fill_pre_wcc(struct svc_fh *fhp)
244{
245	struct inode    *inode;
246
247	inode = fhp->fh_dentry->d_inode;
248	if (!fhp->fh_pre_saved) {
249		fhp->fh_pre_mtime = inode->i_mtime;
250		fhp->fh_pre_ctime = inode->i_ctime;
251			fhp->fh_pre_size  = inode->i_size;
252			fhp->fh_pre_saved = 1;
253	}
254}
255
256/*
257 * Fill in the post_op attr for the wcc data
258 */
259static inline void
260fill_post_wcc(struct svc_fh *fhp)
261{
262	struct inode    *inode = fhp->fh_dentry->d_inode;
263
264	if (fhp->fh_post_saved)
265		printk("nfsd: inode locked twice during operation.\n");
266
267	fhp->fh_post_mode       = inode->i_mode;
268	fhp->fh_post_nlink      = inode->i_nlink;
269	fhp->fh_post_uid	= inode->i_uid;
270	fhp->fh_post_gid	= inode->i_gid;
271	fhp->fh_post_size       = inode->i_size;
272	if (inode->i_blksize) {
273		fhp->fh_post_blksize    = inode->i_blksize;
274		fhp->fh_post_blocks     = inode->i_blocks;
275	} else {
276		fhp->fh_post_blksize    = BLOCK_SIZE;
277		/* how much do we care for accuracy with MinixFS? */
278		fhp->fh_post_blocks     = (inode->i_size+511) >> 9;
279	}
280	fhp->fh_post_rdev[0]    = htonl((u32)imajor(inode));
281	fhp->fh_post_rdev[1]    = htonl((u32)iminor(inode));
282	fhp->fh_post_atime      = inode->i_atime;
283	fhp->fh_post_mtime      = inode->i_mtime;
284	fhp->fh_post_ctime      = inode->i_ctime;
285	fhp->fh_post_saved      = 1;
286}
287#else
288#define	fill_pre_wcc(ignored)
289#define fill_post_wcc(notused)
290#endif /* CONFIG_NFSD_V3 */
291
292
293/*
294 * Lock a file handle/inode
295 * NOTE: both fh_lock and fh_unlock are done "by hand" in
296 * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
297 * so, any changes here should be reflected there.
298 */
299static inline void
300fh_lock(struct svc_fh *fhp)
301{
302	struct dentry	*dentry = fhp->fh_dentry;
303	struct inode	*inode;
304
305	dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
306			SVCFH_fmt(fhp), fhp->fh_locked);
307
308	if (!fhp->fh_dentry) {
309		printk(KERN_ERR "fh_lock: fh not verified!\n");
310		return;
311	}
312	if (fhp->fh_locked) {
313		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
314			dentry->d_parent->d_name.name, dentry->d_name.name);
315		return;
316	}
317
318	inode = dentry->d_inode;
319	mutex_lock(&inode->i_mutex);
320	fill_pre_wcc(fhp);
321	fhp->fh_locked = 1;
322}
323
324/*
325 * Unlock a file handle/inode
326 */
327static inline void
328fh_unlock(struct svc_fh *fhp)
329{
330	if (!fhp->fh_dentry)
331		printk(KERN_ERR "fh_unlock: fh not verified!\n");
332
333	if (fhp->fh_locked) {
334		fill_post_wcc(fhp);
335		mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
336		fhp->fh_locked = 0;
337	}
338}
339#endif /* __KERNEL__ */
340
341
342#endif /* _LINUX_NFSD_FH_H */
343