
---


---

 linux-2.6.18-rc5-andros/fs/nfs/nfs4xdr.c        |  130 ++++++++++++++++++++++++
 linux-2.6.18-rc5-andros/include/linux/nfs4.h    |    1 
 linux-2.6.18-rc5-andros/include/linux/nfs_xdr.h |   11 ++
 3 files changed, 142 insertions(+)

diff -puN fs/nfs/nfs4xdr.c~nfs-secinfo-xdr fs/nfs/nfs4xdr.c
--- linux-2.6.18-rc5/fs/nfs/nfs4xdr.c~nfs-secinfo-xdr	2006-10-11 17:36:53.000000000 -0400
+++ linux-2.6.18-rc5-andros/fs/nfs/nfs4xdr.c	2006-10-11 17:36:53.000000000 -0400
@@ -47,6 +47,7 @@
 #include <linux/proc_fs.h>
 #include <linux/kdev_t.h>
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/gss_api.h>
 #include <linux/nfs.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
@@ -92,6 +93,8 @@ static int nfs4_stat_to_errno(int);
 				3 + 3 + 3 + 2 * nfs4_name_maxsz))
 #define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
 				nfs4_fattr_value_maxsz)
+#define gss_oid_maxsz		(GSS_OID_MAX_LEN >> 2)
+#define nfs4_flav_info_maxsz	(1 + gss_oid_maxsz + 1 + 1)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
 #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
 #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
@@ -137,6 +140,10 @@ static int nfs4_stat_to_errno(int);
 #define decode_create_maxsz	(op_decode_hdr_maxsz + 8)
 #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
 #define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
+#define encode_secinfo_maxsz   (op_encode_hdr_maxsz + 1 + nfs4_name_maxsz)
+#define decode_secinfo_maxsz   (op_decode_hdr_maxsz +	\
+				(1 + nfs4_flav_info_maxsz) * \
+				NFS4_SECINFO_MAXFLAVORS)
 #define NFS4_enc_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_dec_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_enc_read_sz	(compound_encode_hdr_maxsz + \
@@ -420,6 +427,12 @@ static int nfs4_stat_to_errno(int);
 				 decode_putfh_maxsz + \
 				 op_decode_hdr_maxsz + \
 				 nfs4_fattr_bitmap_maxsz)
+#define NFS4_enc_secinfo_sz    (compound_encode_hdr_maxsz + \
+				 encode_putfh_maxsz + \
+				 encode_secinfo_maxsz)
+#define NFS4_dec_secinfo_sz    (compound_decode_hdr_maxsz + \
+				 decode_putfh_maxsz + \
+				 decode_secinfo_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -1212,6 +1225,18 @@ encode_savefh(struct xdr_stream *xdr)
 	return 0;
 }
 
+static int encode_secinfo(struct xdr_stream *xdr, const struct qstr *name)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(8 + name->len);
+	WRITE32(OP_SECINFO);
+	WRITE32(name->len);
+	WRITEMEM(name->name, name->len);
+
+	return 0;
+}
+
 static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server)
 {
 	int status;
@@ -1900,6 +1925,25 @@ static int nfs4_xdr_enc_pathconf(struct 
 }
 
 /*
+* Encode SECINFO request
+*/
+static int nfs4_xdr_enc_secinfo(struct rpc_rqst *req, uint32_t *p, const struct nfs4_secinfo_arg *args)
+{
+	int status;
+	struct xdr_stream xdr;
+	struct compound_hdr hdr = {
+		.nops = 2,
+	};
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, &hdr);
+	status = encode_putfh(&xdr, args->dir_fh);
+	if (!status)
+		status = encode_secinfo(&xdr, args->name);
+	return status;
+}
+
+/*
  * a STATFS request
  */
 static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args)
@@ -3549,6 +3593,73 @@ decode_savefh(struct xdr_stream *xdr)
 	return decode_op_hdr(xdr, OP_SAVEFH);
 }
 
+/* Is a printk needed if
+ * 	num_flavors is too big,
+ * 	flavor is too big,
+ * 	oidlen is too big,
+ * 	or if we don't support a pseudoflavor?
+ *
+ * Only decode (in order) the pseudoflavors supported by the client.
+ */
+static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+{
+	uint32_t *p;
+	uint32_t qop;
+	uint32_t service;
+	int status;
+	int i;
+	rpc_authflavor_t flavor;
+	int oidlen;
+	char oiddata[GSS_OID_MAX_LEN];
+
+	status = decode_op_hdr(xdr, OP_SECINFO);
+	if (status)
+		return status;
+
+	READ_BUF(4);
+	READ32(res->nflavors);
+	if (res->nflavors > NFS4_SECINFO_MAXFLAVORS)
+		res->nflavors = NFS4_SECINFO_MAXFLAVORS;
+
+	for (i = 0; i < res->nflavors; i++) {
+		READ_BUF(4);
+		READ32(flavor);
+		if (flavor > RPC_AUTH_MAXFLAVOR)
+			/* XXX -EINVAL ?? */
+			continue;
+		switch (flavor) {
+			case RPC_AUTH_GSS:
+				/* oid */
+				READ_BUF(4);
+				READ32(oidlen);
+				if (oidlen > GSS_OID_MAX_LEN)
+					/* XXX -EINVAL ?*/
+					return -EINVAL;
+				READ_BUF(oidlen);
+				COPYMEM(oiddata, oidlen);
+
+				/* qop - ignore for now */
+				READ_BUF(4);
+				READ32(qop);
+
+				/* service */
+				READ_BUF(4);
+				READ32(service);
+				res->flavors[i] =
+					gss_triple_to_pseudoflavor(oidlen,
+							oiddata, service);
+				break;
+			case RPC_AUTH_UNIX:
+			case RPC_AUTH_NULL:
+			default:
+				res->flavors[i] = flavor;
+				break;
+		}
+	}
+	return 0;
+}
+
+
 static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res)
 {
 	uint32_t *p;
@@ -4278,6 +4389,24 @@ static int nfs4_xdr_dec_pathconf(struct 
 	return status;
 }
 
+ /*
+  * Decode SECINFO response
+  */
+static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_secinfo_res *res)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (!status)
+		status = decode_putfh(&xdr);
+	if (!status)
+		status = decode_secinfo(&xdr, res);
+	return status;
+}
+
 /*
  * STATFS request
  */
@@ -4589,6 +4718,7 @@ struct rpc_procinfo	nfs4_procedures[] = 
   PROC(GETACL,		enc_getacl,	dec_getacl),
   PROC(SETACL,		enc_setacl,	dec_setacl),
   PROC(FS_LOCATIONS,	enc_fs_locations, dec_fs_locations),
+  PROC(SECINFO,		enc_secinfo,	dec_secinfo),
 };
 
 struct rpc_version		nfs_version4 = {
diff -puN include/linux/nfs4.h~nfs-secinfo-xdr include/linux/nfs4.h
--- linux-2.6.18-rc5/include/linux/nfs4.h~nfs-secinfo-xdr	2006-10-11 17:36:53.000000000 -0400
+++ linux-2.6.18-rc5-andros/include/linux/nfs4.h	2006-10-11 17:36:53.000000000 -0400
@@ -391,6 +391,7 @@ enum {
 	NFSPROC4_CLNT_GETACL,
 	NFSPROC4_CLNT_SETACL,
 	NFSPROC4_CLNT_FS_LOCATIONS,
+	NFSPROC4_CLNT_SECINFO,
 };
 
 #endif
diff -puN include/linux/nfs_xdr.h~nfs-secinfo-xdr include/linux/nfs_xdr.h
--- linux-2.6.18-rc5/include/linux/nfs_xdr.h~nfs-secinfo-xdr	2006-10-11 17:36:53.000000000 -0400
+++ linux-2.6.18-rc5-andros/include/linux/nfs_xdr.h	2006-10-11 17:36:53.000000000 -0400
@@ -320,6 +320,17 @@ struct nfs_renameargs {
 	unsigned int		tolen;
 };
 
+struct nfs4_secinfo_arg {
+	const struct nfs_fh *           dir_fh;
+	const struct qstr *             name;
+};
+
+#define NFS4_SECINFO_MAXFLAVORS		12
+struct nfs4_secinfo_res {
+	unsigned int 		nflavors;
+	rpc_authflavor_t	flavors[NFS4_SECINFO_MAXFLAVORS];
+};
+
 struct nfs_setattrargs {
 	struct nfs_fh *                 fh;
 	nfs4_stateid                    stateid;
_
