Example #1
0
static int decode_filename_inline(struct xdr_stream *xdr,
				  const char **name, u32 *length)
{
	__be32 *p;
	u32 count;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	count = be32_to_cpup(p);
	if (count > NFS3_MAXNAMLEN)
		goto out_nametoolong;
	p = xdr_inline_decode(xdr, count);
	if (unlikely(p == NULL))
		goto out_overflow;
	*name = (const char *)p;
	*length = count;
	return 0;
out_nametoolong:
	dprintk("NFS: returned filename too long: %u\n", count);
	return -ENAMETOOLONG;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #2
0
static int
unx_validate(struct rpc_task *task, struct xdr_stream *xdr)
{
	struct rpc_auth *auth = task->tk_rqstp->rq_cred->cr_auth;
	__be32 *p;
	u32 size;

	p = xdr_inline_decode(xdr, 2 * sizeof(*p));
	if (!p)
		return -EIO;
	switch (*p++) {
	case rpc_auth_null:
	case rpc_auth_unix:
	case rpc_auth_short:
		break;
	default:
		return -EIO;
	}
	size = be32_to_cpup(p);
	if (size > RPC_MAX_AUTH_SIZE)
		return -EIO;
	p = xdr_inline_decode(xdr, size);
	if (!p)
		return -EIO;

	auth->au_verfsize = XDR_QUADLEN(size) + 2;
	auth->au_rslack = XDR_QUADLEN(size) + 2;
	auth->au_ralign = XDR_QUADLEN(size) + 2;
	return 0;
}
Example #3
0
static int decode_cookie(struct xdr_stream *xdr,
			 struct nlm_cookie *cookie)
{
	u32 length;
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	length = be32_to_cpup(p++);
	/* apparently HPUX can return empty cookies */
	if (length == 0)
		goto out_hpux;
	if (length > NLM_MAXCOOKIELEN)
		goto out_size;
	p = xdr_inline_decode(xdr, length);
	if (unlikely(p == NULL))
		goto out_overflow;
	cookie->len = length;
	memcpy(cookie->data, p, length);
	return 0;
out_hpux:
	cookie->len = 4;
	memset(cookie->data, 0, 4);
	return 0;
out_size:
	dprintk("NFS: returned cookie was too long: %u\n", length);
	return -EIO;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #4
0
static int decode_filename(struct xdr_stream *xdr,
		char *name, u32 *length)
{
	__be32 *p;
	u32 count;

	p = xdr_inline_decode(xdr, 4);
	if (!p)
		goto out_overflow;
	count = be32_to_cpup(p);
	if (count > 255)
		goto out_nametoolong;
	p = xdr_inline_decode(xdr, count);
	if (!p)
		goto out_overflow;
	memcpy(name, p, count);
	name[count] = 0;
	*length = count;
	return 0;
out_nametoolong:
	printk("NFS: returned filename too long: %u\n", count);
	return -ENAMETOOLONG;
out_overflow:
	printf("%s overflow\n",__func__);
	return -EIO;
}
Example #5
0
static int gssx_dec_buffer(struct xdr_stream *xdr,
			   gssx_buffer *buf)
{
	u32 length;
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		return -ENOSPC;

	length = be32_to_cpup(p);
	p = xdr_inline_decode(xdr, length);
	if (unlikely(p == NULL))
		return -ENOSPC;

	if (buf->len == 0) {
		/* we intentionally are not interested in this buffer */
		return 0;
	}
	if (length > buf->len)
		return -ENOSPC;

	if (!buf->data) {
		buf->data = kmemdup(p, length, GFP_KERNEL);
		if (!buf->data)
			return -ENOMEM;
	} else {
		memcpy(buf->data, p, length);
	}
	buf->len = length;
	return 0;
}
Example #6
0
static int gssx_dec_linux_creds(struct xdr_stream *xdr,
				struct svc_cred *creds)
{
	u32 length;
	__be32 *p;
	u32 tmp;
	u32 N;
	int i, err;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		return -ENOSPC;

	length = be32_to_cpup(p);

	if (length > (3 + NGROUPS_MAX) * sizeof(u32))
		return -ENOSPC;

	/* uid */
	err = get_host_u32(xdr, &tmp);
	if (err)
		return err;
	creds->cr_uid = make_kuid(&init_user_ns, tmp);

	/* gid */
	err = get_host_u32(xdr, &tmp);
	if (err)
		return err;
	creds->cr_gid = make_kgid(&init_user_ns, tmp);

	/* number of additional gid's */
	err = get_host_u32(xdr, &tmp);
	if (err)
		return err;
	N = tmp;
	if ((3 + N) * sizeof(u32) != length)
		return -EINVAL;
	creds->cr_group_info = groups_alloc(N);
	if (creds->cr_group_info == NULL)
		return -ENOMEM;

	/* gid's */
	for (i = 0; i < N; i++) {
		kgid_t kgid;
		err = get_host_u32(xdr, &tmp);
		if (err)
			goto out_free_groups;
		err = -EINVAL;
		kgid = make_kgid(&init_user_ns, tmp);
		if (!gid_valid(kgid))
			goto out_free_groups;
		creds->cr_group_info->gid[i] = kgid;
	}
	groups_sort(creds->cr_group_info);

	return 0;
out_free_groups:
	groups_free(creds->cr_group_info);
	return err;
}
Example #7
0
/*
 *	typedef opaque	nfsdata<>;
 */
static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
{
	u32 recvd, count;
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	count = be32_to_cpup(p);
	recvd = xdr_read_pages(xdr, count);
	if (unlikely(count > recvd))
		goto out_cheating;
out:
	result->eof = 0;	/* NFSv2 does not pass EOF flag on the wire. */
	result->count = count;
	return count;
out_cheating:
	dprintk("NFS: server cheating in read result: "
		"count %u > recvd %u\n", count, recvd);
	count = recvd;
	goto out;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #8
0
static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
{
	umode_t fmode;
	__be32 *p;

	p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
	if (unlikely(p == NULL))
		goto out_overflow;

	p = xdr_decode_ftype3(p, &fmode);

	fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
	fattr->nlink = be32_to_cpup(p++);
	fattr->uid = be32_to_cpup(p++);
	fattr->gid = be32_to_cpup(p++);

	p = xdr_decode_size3(p, &fattr->size);
	p = xdr_decode_size3(p, &fattr->du.nfs3.used);
	p = xdr_decode_specdata3(p, &fattr->rdev);

	p = xdr_decode_hyper(p, &fattr->fsid.major);
	fattr->fsid.minor = 0;

	p = xdr_decode_fileid3(p, &fattr->fileid);
	p = xdr_decode_nfstime3(p, &fattr->atime);
	p = xdr_decode_nfstime3(p, &fattr->mtime);
	xdr_decode_nfstime3(p, &fattr->ctime);

	fattr->valid |= NFS_ATTR_FATTR_V3;
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #9
0
static int decode_path(struct xdr_stream *xdr)
{
	u32 length, recvd;
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	length = be32_to_cpup(p);
	if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
		goto out_size;
	recvd = xdr_read_pages(xdr, length);
	if (unlikely(length > recvd))
		goto out_cheating;
	xdr_terminate_string(xdr->buf, length);
	return 0;
out_size:
	dprintk("NFS: returned pathname too long: %u\n", length);
	return -ENAMETOOLONG;
out_cheating:
	dprintk("NFS: server cheating in pathname result: "
		"length %u > received %u\n", length, recvd);
	return -EIO;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #10
0
static int decode_nfspath3(struct xdr_stream *xdr)
{
	u32 recvd, count;
	size_t hdrlen;
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	count = be32_to_cpup(p);
	if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
		goto out_nametoolong;
	hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
	recvd = xdr->buf->len - hdrlen;
	if (unlikely(count > recvd))
		goto out_cheating;

	xdr_read_pages(xdr, count);
	xdr_terminate_string(xdr->buf, count);
	return 0;

out_nametoolong:
	dprintk("NFS: returned pathname too long: %u\n", count);
	return -ENAMETOOLONG;
out_cheating:
	dprintk("NFS: server cheating in pathname result: "
		"count %u > recvd %u\n", count, recvd);
	return -EIO;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #11
0
static int decode_fsinfo3resok(struct xdr_stream *xdr,
			       struct nfs_fsinfo *result)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	result->rtmax  = be32_to_cpup(p++);
	result->rtpref = be32_to_cpup(p++);
	result->rtmult = be32_to_cpup(p++);
	result->wtmax  = be32_to_cpup(p++);
	result->wtpref = be32_to_cpup(p++);
	result->wtmult = be32_to_cpup(p++);
	result->dtpref = be32_to_cpup(p++);
	p = xdr_decode_size3(p, &result->maxfilesize);
	xdr_decode_nfstime3(p, &result->time_delta);

	
	result->lease_time = 0;
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #12
0
/**
 * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
 *                      the local page cache.
 * @xdr: XDR stream where entry resides
 * @entry: buffer to fill in with entry data
 * @plus: boolean indicating whether this should be a readdirplus entry
 *
 * Returns zero if successful, otherwise a negative errno value is
 * returned.
 *
 * This function is not invoked during READDIR reply decoding, but
 * rather whenever an application invokes the getdents(2) system call
 * on a directory already in our cache.
 *
 * 2.2.17.  entry
 *
 *	struct entry {
 *		unsigned	fileid;
 *		filename	name;
 *		nfscookie	cookie;
 *		entry		*nextentry;
 *	};
 */
int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
		       int plus)
{
	__be32 *p;
	int error;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	if (*p++ == xdr_zero) {
		p = xdr_inline_decode(xdr, 4);
		if (unlikely(p == NULL))
			goto out_overflow;
		if (*p++ == xdr_zero)
			return -EAGAIN;
		entry->eof = 1;
		return -EBADCOOKIE;
	}

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	entry->ino = be32_to_cpup(p);

	error = decode_filename_inline(xdr, &entry->name, &entry->len);
	if (unlikely(error))
		return error;

	/*
	 * The type (size and byte order) of nfscookie isn't defined in
	 * RFC 1094.  This implementation assumes that it's an XDR uint32.
	 */
	entry->prev_cookie = entry->cookie;
	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	entry->cookie = be32_to_cpup(p);

	entry->d_type = DT_UNKNOWN;

	return 0;

out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EAGAIN;
}
static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
{
	struct nlm_lock *lock = &result->lock;
	struct file_lock *fl = &lock->fl;
	u64 l_offset, l_len;
	u32 exclusive;
	int error;
	__be32 *p;
	s32 end;

	memset(lock, 0, sizeof(*lock));
	locks_init_lock(fl);

	p = xdr_inline_decode(xdr, 4 + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	exclusive = be32_to_cpup(p++);
	lock->svid = be32_to_cpup(p);
	fl->fl_pid = (pid_t)lock->svid;

	error = decode_netobj(xdr, &lock->oh);
	if (unlikely(error))
		goto out;

	p = xdr_inline_decode(xdr, 8 + 8);
	if (unlikely(p == NULL))
		goto out_overflow;

	fl->fl_flags = FL_POSIX;
	fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
	p = xdr_decode_hyper(p, &l_offset);
	xdr_decode_hyper(p, &l_len);
	end = l_offset + l_len - 1;

	fl->fl_start = (loff_t)l_offset;
	if (l_len == 0 || end < 0)
		fl->fl_end = OFFSET_MAX;
	else
		fl->fl_end = (loff_t)end;
	error = 0;
out:
	return error;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #14
0
static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes)
{
	uint32_t *p;

	p = xdr_inline_decode(xdr, nbytes);
	if (unlikely(p == NULL))
		printk(KERN_WARNING "NFSv4 callback reply buffer overflowed!\n");
	return p;
}
static int
_osd_xdr_decode_opaque_cred(struct pnfs_osd_opaque_cred *opaque_cred,
			    struct xdr_stream *xdr)
{
	__be32 *p = xdr_inline_decode(xdr, 1);

	if (!p)
		return -EINVAL;

	opaque_cred->cred_len = be32_to_cpu(*p++);

	p = xdr_inline_decode(xdr, opaque_cred->cred_len);
	if (!p)
		return -EINVAL;

	opaque_cred->cred = p;
	return 0;
}
Example #16
0
File: dev.c Project: AK101111/linux
struct nfs4_deviceid_node *
bl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
		gfp_t gfp_mask)
{
	struct nfs4_deviceid_node *node = NULL;
	struct pnfs_block_volume *volumes;
	struct pnfs_block_dev *top;
	struct xdr_stream xdr;
	struct xdr_buf buf;
	struct page *scratch;
	int nr_volumes, ret, i;
	__be32 *p;

	scratch = alloc_page(gfp_mask);
	if (!scratch)
		goto out;

	xdr_init_decode_pages(&xdr, &buf, pdev->pages, pdev->pglen);
	xdr_set_scratch_buffer(&xdr, page_address(scratch), PAGE_SIZE);

	p = xdr_inline_decode(&xdr, sizeof(__be32));
	if (!p)
		goto out_free_scratch;
	nr_volumes = be32_to_cpup(p++);

	volumes = kcalloc(nr_volumes, sizeof(struct pnfs_block_volume),
			  gfp_mask);
	if (!volumes)
		goto out_free_scratch;

	for (i = 0; i < nr_volumes; i++) {
		ret = nfs4_block_decode_volume(&xdr, &volumes[i]);
		if (ret < 0)
			goto out_free_volumes;
	}

	top = kzalloc(sizeof(*top), gfp_mask);
	if (!top)
		goto out_free_volumes;

	ret = bl_parse_deviceid(server, top, volumes, nr_volumes - 1, gfp_mask);
	if (ret) {
		bl_free_device(top);
		kfree(top);
		goto out_free_volumes;
	}

	node = &top->node;
	nfs4_init_deviceid_node(node, server, &pdev->dev_id);

out_free_volumes:
	kfree(volumes);
out_free_scratch:
	__free_page(scratch);
out:
	return node;
}
Example #17
0
__be32 *
nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
{
	__be32 *p;
	p = xdr_inline_decode(xdr, 4);
	if (unlikely(!p))
		goto out_overflow;
	if (!ntohl(*p++)) {
		p = xdr_inline_decode(xdr, 4);
		if (unlikely(!p))
			goto out_overflow;
		if (!ntohl(*p++))
			return ERR_PTR(-EAGAIN);
		entry->eof = 1;
		return ERR_PTR(-EBADCOOKIE);
	}

	p = xdr_inline_decode(xdr, 8);
	if (unlikely(!p))
		goto out_overflow;

	entry->ino	  = ntohl(*p++);
	entry->len	  = ntohl(*p++);

	p = xdr_inline_decode(xdr, entry->len + 4);
	if (unlikely(!p))
		goto out_overflow;
	entry->name	  = (const char *) p;
	p		 += XDR_QUADLEN(entry->len);
	entry->prev_cookie	  = entry->cookie;
	entry->cookie	  = ntohl(*p++);

	p = xdr_inline_peek(xdr, 8);
	if (p != NULL)
		entry->eof = !p[0] && p[1];
	else
		entry->eof = 0;

	return p;

out_overflow:
	print_overflow_msg(__func__, xdr);
	return ERR_PTR(-EIO);
}
Example #18
0
static int gssx_dec_status(struct xdr_stream *xdr,
			   struct gssx_status *status)
{
	__be32 *p;
	int err;

	/* status->major_status */
	p = xdr_inline_decode(xdr, 8);
	if (unlikely(p == NULL))
		return -ENOSPC;
	p = xdr_decode_hyper(p, &status->major_status);

	/* status->mech */
	err = gssx_dec_buffer(xdr, &status->mech);
	if (err)
		return err;

	/* status->minor_status */
	p = xdr_inline_decode(xdr, 8);
	if (unlikely(p == NULL))
		return -ENOSPC;
	p = xdr_decode_hyper(p, &status->minor_status);

	/* status->major_status_string */
	err = gssx_dec_buffer(xdr, &status->major_status_string);
	if (err)
		return err;

	/* status->minor_status_string */
	err = gssx_dec_buffer(xdr, &status->minor_status_string);
	if (err)
		return err;

	/* status->server_ctx */
	err = gssx_dec_buffer(xdr, &status->server_ctx);
	if (err)
		return err;

	/* we assume we have no options for now, so simply consume them */
	/* status->options */
	err = dummy_dec_opt_array(xdr, &status->options);

	return err;
}
Example #19
0
static inline __be32 *
xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(!p))
		goto out_overflow;
	if (ntohl(*p++)) {
		p = xdr_inline_decode(xdr, 84);
		if (unlikely(!p))
			goto out_overflow;
		p = xdr_decode_fattr(p, fattr);
	}
	return p;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return ERR_PTR(-EIO);
}
Example #20
0
static int gssx_dec_bool(struct xdr_stream *xdr, u32 *v)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		return -ENOSPC;
	*v = be32_to_cpu(*p);
	return 0;
}
Example #21
0
__be32 *
nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
{
	__be32 *p;
	p = xdr_inline_decode(xdr, 4);
	if (unlikely(!p))
		goto out_overflow;
	if (!ntohl(*p++)) {
		p = xdr_inline_decode(xdr, 4);
		if (unlikely(!p))
			goto out_overflow;
		if (!ntohl(*p++))
			return ERR_PTR(-EAGAIN);
		entry->eof = 1;
		return ERR_PTR(-EBADCOOKIE);
	}

	p = xdr_inline_decode(xdr, 8);
	if (unlikely(!p))
		goto out_overflow;

	entry->ino	  = ntohl(*p++);
	entry->len	  = ntohl(*p++);

	p = xdr_inline_decode(xdr, entry->len);
	if (unlikely(!p))
		goto out_overflow;
	entry->name	  = (const char *) p;
	p = xdr_inline_decode(xdr, 4);
	if (unlikely(!p))
		goto out_overflow;
	entry->prev_cookie	  = entry->cookie;
	entry->cookie	  = be32_to_cpup(p);

	entry->d_type = DT_UNKNOWN;

	return p;

out_overflow:
	print_overflow_msg(__func__, xdr);
	return ERR_PTR(-EAGAIN);
}
Example #22
0
static int get_host_u32(struct xdr_stream *xdr, u32 *res)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (!p)
		return -EINVAL;
	/* Contents of linux creds are all host-endian: */
	memcpy(res, p, sizeof(u32));
	return 0;
}
Example #23
0
/*
 * CB_COMPOUND4res
 *
 *	struct CB_COMPOUND4res {
 *		nfsstat4	status;
 *		utf8str_cs	tag;
 *		nfs_cb_resop4	resarray<>;
 *	};
 */
static int decode_cb_compound4res(struct xdr_stream *xdr,
				  struct nfs4_cb_compound_hdr *hdr)
{
	u32 length;
	__be32 *p;

	p = xdr_inline_decode(xdr, 4 + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	hdr->status = be32_to_cpup(p++);
	/* Ignore the tag */
	length = be32_to_cpup(p++);
	p = xdr_inline_decode(xdr, length + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	hdr->nops = be32_to_cpup(p);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #24
0
static int decode_uint32(struct xdr_stream *xdr, u32 *value)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	*value = be32_to_cpup(p);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #25
0
static inline __be32 *
xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
{
	__be32 *p;
	p = xdr_inline_decode(xdr, 4);
	if (unlikely(!p))
		goto out_overflow;
	fh->size = ntohl(*p++);

	if (fh->size <= NFS3_FHSIZE) {
		p = xdr_inline_decode(xdr, fh->size);
		if (unlikely(!p))
			goto out_overflow;
		memcpy(fh->data, p, fh->size);
		return p + XDR_QUADLEN(fh->size);
	}
	return NULL;

out_overflow:
	print_overflow_msg(__func__, xdr);
	return ERR_PTR(-EIO);
}
Example #26
0
static int decode_uint64(struct xdr_stream *xdr, u64 *value)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, 8);
	if (unlikely(p == NULL))
		goto out_overflow;
	xdr_decode_hyper(p, value);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #27
0
static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
	if (unlikely(p == NULL))
		goto out_overflow;
	memcpy(verifier, p, NFS3_WRITEVERFSIZE);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #28
0
static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
{
	__be32 *p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	if (*p != xdr_zero)
		return decode_nfs_fh3(xdr, fh);
	zero_nfs_fh3(fh);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #29
0
/*
 *	enum stat {
 *		NFS_OK = 0,
 *		NFSERR_PERM = 1,
 *		NFSERR_NOENT = 2,
 *		NFSERR_IO = 5,
 *		NFSERR_NXIO = 6,
 *		NFSERR_ACCES = 13,
 *		NFSERR_EXIST = 17,
 *		NFSERR_NODEV = 19,
 *		NFSERR_NOTDIR = 20,
 *		NFSERR_ISDIR = 21,
 *		NFSERR_FBIG = 27,
 *		NFSERR_NOSPC = 28,
 *		NFSERR_ROFS = 30,
 *		NFSERR_NAMETOOLONG = 63,
 *		NFSERR_NOTEMPTY = 66,
 *		NFSERR_DQUOT = 69,
 *		NFSERR_STALE = 70,
 *		NFSERR_WFLUSH = 99
 *	};
 */
static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
{
	__be32 *p;

	p = xdr_inline_decode(xdr, 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	*status = be32_to_cpup(p);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
Example #30
0
/*
 * CB_SEQUENCE4resok
 *
 *	struct CB_SEQUENCE4resok {
 *		sessionid4	csr_sessionid;
 *		sequenceid4	csr_sequenceid;
 *		slotid4		csr_slotid;
 *		slotid4		csr_highest_slotid;
 *		slotid4		csr_target_highest_slotid;
 *	};
 *
 *	union CB_SEQUENCE4res switch (nfsstat4 csr_status) {
 *	case NFS4_OK:
 *		CB_SEQUENCE4resok	csr_resok4;
 *	default:
 *		void;
 *	};
 *
 * Our current back channel implmentation supports a single backchannel
 * with a single slot.
 */
static int decode_cb_sequence4resok(struct xdr_stream *xdr,
				    struct nfsd4_callback *cb)
{
	struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
	struct nfs4_sessionid id;
	int status;
	__be32 *p;
	u32 dummy;

	status = -ESERVERFAULT;

	/*
	 * If the server returns different values for sessionID, slotID or
	 * sequence number, the server is looney tunes.
	 */
	p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
	if (memcmp(id.data, session->se_sessionid.data,
					NFS4_MAX_SESSIONID_LEN) != 0) {
		dprintk("NFS: %s Invalid session id\n", __func__);
		goto out;
	}
	p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);

	dummy = be32_to_cpup(p++);
	if (dummy != session->se_cb_seq_nr) {
		dprintk("NFS: %s Invalid sequence number\n", __func__);
		goto out;
	}

	dummy = be32_to_cpup(p++);
	if (dummy != 0) {
		dprintk("NFS: %s Invalid slotid\n", __func__);
		goto out;
	}

	/*
	 * FIXME: process highest slotid and target highest slotid
	 */
	status = 0;
out:
	if (status)
		nfsd4_mark_cb_fault(cb->cb_clp, status);
	return status;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}