mount_9p: add initial support for 9P2000.u trunk
authorozaki-r <ozaki-r@NetBSD.org>
Fri, 17 May 2019 08:48:04 +0000
branchtrunk
changeset 451353 b3c44e1994d8
parent 451352 b60f2a135671
child 451354 264188ae84d3
mount_9p: add initial support for 9P2000.u The implementation enables to work with a server talking 9P2000.u. However, it doesn't use the extended fields yet; it just ignores those of received messages and sets "please ignore" values to those of sending messages such as zero-length strings and maximum unsigned values. The feature is enabled by the -u option.
usr.sbin/puffs/mount_9p/fs.c
usr.sbin/puffs/mount_9p/mount_9p.8
usr.sbin/puffs/mount_9p/nineproto.c
usr.sbin/puffs/mount_9p/nineproto.h
usr.sbin/puffs/mount_9p/ninepuffs.c
usr.sbin/puffs/mount_9p/ninepuffs.h
usr.sbin/puffs/mount_9p/node.c
--- a/usr.sbin/puffs/mount_9p/fs.c	Fri May 17 08:26:20 2019 +0000
+++ b/usr.sbin/puffs/mount_9p/fs.c	Fri May 17 08:48:04 2019 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: fs.c,v 1.9 2011/06/22 04:03:23 mrg Exp $	*/
+/*	$NetBSD: fs.c,v 1.10 2019/05/17 08:48:04 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: fs.c,v 1.9 2011/06/22 04:03:23 mrg Exp $");
+__RCSID("$NetBSD: fs.c,v 1.10 2019/05/17 08:48:04 ozaki-r Exp $");
 #endif /* !lint */
 
 #include <assert.h>
@@ -48,6 +48,17 @@
 	rv = fname(a1, a2, a3, a4);					\
 	if (rv) errx(1, "p9p_handshake io failed %d, %d", rv, *a4) 
 
+static const char *
+p9p_ver2str(int version)
+{
+
+	switch (version) {
+	case P9PROTO_VERSION:	return P9PROTO_VERSTR;
+	case P9PROTO_VERSION_U:	return P9PROTO_VERSTR_U;
+	}
+	return NULL;
+}
+
 struct puffs_node *
 p9p_handshake(struct puffs_usermount *pu,
 	const char *username, const char *path)
@@ -63,13 +74,15 @@
 	const char *p;
 	uint8_t type;
 	int rv, done, x = 1, ncomp;
+	uint16_t strsize;
+	char *str;
 
 	/* send initial handshake */
 	pb = p9pbuf_makeout();
 	p9pbuf_put_1(pb, P9PROTO_T_VERSION);
 	p9pbuf_put_2(pb, P9PROTO_NOTAG);
 	p9pbuf_put_4(pb, p9p->maxreq);
-	p9pbuf_put_str(pb, P9PROTO_VERSION);
+	p9pbuf_put_str(pb, p9p_ver2str(p9p->protover));
 	DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
 
 	puffs_framebuf_recycle(pb);
@@ -89,6 +102,13 @@
 		    "%d vs. %d", P9P_MINREQLEN, maxreq);
 	p9p->maxreq = maxreq;
 
+	if (p9pbuf_get_str(pb, &str, &strsize))
+		errx(1, "server invalid response: no version");
+	if (strncmp(str, p9p_ver2str(p9p->protover), P9PROTO_VERSTR_MAXLEN) != 0) {
+		errx(1, "server doesn't support %s", p9p_ver2str(p9p->protover));
+		/* Should downgrade from 9P2000.u to 9P2000 if the server request? */
+	}
+
 	/* tell the server we don't support authentication */
 	p9pbuf_recycleout(pb);
 	tagid = NEXTTAG(p9p);
@@ -97,6 +117,8 @@
 	p9pbuf_put_4(pb, P9PROTO_NOFID);
 	p9pbuf_put_str(pb, username);
 	p9pbuf_put_str(pb, "");
+	if (p9p->protover == P9PROTO_VERSION_U)
+		p9pbuf_put_4(pb, P9PROTO_NUNAME_UNSPECIFIED); /* n_uname[4] */
 	DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
 
 	puffs_framebuf_recycle(pb);
@@ -117,6 +139,8 @@
 	p9pbuf_put_4(pb, P9PROTO_NOFID);
 	p9pbuf_put_str(pb, username);
 	p9pbuf_put_str(pb, "");
+	if (p9p->protover == P9PROTO_VERSION_U)
+		p9pbuf_put_4(pb, P9PROTO_NUNAME_UNSPECIFIED); /* n_uname[4] */
 	DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
 
 	puffs_framebuf_recycle(pb);
@@ -213,7 +237,7 @@
 		errx(1, "server invalid tag: %d vs. %d", tagid, rtagid);
 	if (p9pbuf_get_2(pb, &dummy))
 		errx(1, "couldn't get stat len parameter");
-	if (proto_getstat(pb, &rootva, NULL, NULL))
+	if (proto_getstat(pu, pb, &rootva, NULL, NULL))
 		errx(1, "could not parse root attributes");
 	puffs_framebuf_destroy(pb);
 
--- a/usr.sbin/puffs/mount_9p/mount_9p.8	Fri May 17 08:26:20 2019 +0000
+++ b/usr.sbin/puffs/mount_9p/mount_9p.8	Fri May 17 08:48:04 2019 +0000
@@ -1,4 +1,4 @@
-.\"	$NetBSD: mount_9p.8,v 1.7 2019/05/17 08:26:20 wiz Exp $
+.\"	$NetBSD: mount_9p.8,v 1.8 2019/05/17 08:48:04 ozaki-r Exp $
 .\"
 .\" Copyright (c) 2007 Antti Kantee.  All rights reserved.
 .\"
@@ -32,6 +32,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl s
+.Op Fl u
 .Op Fl o Ar mntopts
 .Op Fl p Ar port
 .Ar [user@]host[:path]
@@ -61,6 +62,16 @@
 option
 .Nm
 runs in the forground.
+.Pp
+By default
+.Nm
+follows the 9P2000 protocol.
+With
+.Fl u
+option
+.Nm
+follows the 9P2000.u protocol that includes extensions to better support Unix
+environments.
 .Sh SEE ALSO
 .Xr puffs 3 ,
 .Xr puffs 4 ,
@@ -74,6 +85,9 @@
 .Nm
 utility first appeared in
 .Nx 5.0 .
+.Pp
+Experimental 9P2000.u support appeared in
+.Nx 9.0 .
 .Sh CAVEATS
 Permissions are not handled well.
 .Pp
@@ -82,3 +96,5 @@
 Error code handling is missing.
 .Pp
 Under construction.
+.Pp
+9P2000.u support doesn't use extension fields.
--- a/usr.sbin/puffs/mount_9p/nineproto.c	Fri May 17 08:26:20 2019 +0000
+++ b/usr.sbin/puffs/mount_9p/nineproto.c	Fri May 17 08:48:04 2019 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nineproto.c,v 1.9 2007/11/30 19:02:38 pooka Exp $	*/
+/*	$NetBSD: nineproto.c,v 1.10 2019/05/17 08:48:04 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: nineproto.c,v 1.9 2007/11/30 19:02:38 pooka Exp $");
+__RCSID("$NetBSD: nineproto.c,v 1.10 2019/05/17 08:48:04 ozaki-r Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -117,9 +117,10 @@
 	size -= *strsize;						\
 } while (/*CONSTCOND*/0)
 int
-proto_getstat(struct puffs_framebuf *pb, struct vattr *vap,
+proto_getstat(struct puffs_usermount *pu, struct puffs_framebuf *pb, struct vattr *vap,
 	char **name, uint16_t *rs)
 {
+	struct puffs9p *p9p = puffs_getspecific(pu);
 	char *uid, *gid;
 	struct qid9p qid;
 	uint64_t flen;
@@ -176,6 +177,13 @@
 
 	/* muid, not used */
 	GETSTR(NULL, &v16);
+	if (p9p->protover == P9PROTO_VERSION_U) {
+		uint32_t dummy;
+		GETSTR(NULL, &v16); /* extention[s], not used */
+		GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_uid[4], not used */
+		GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_gid[4], not used */
+		GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_muid[4], not used */
+	}
 
 	return 0;
 }
@@ -269,9 +277,10 @@
 }
 
 void
-proto_make_stat(struct puffs_framebuf *pb, const struct vattr *vap,
-	const char *filename, enum vtype vt)
+proto_make_stat(struct puffs_usermount *pu, struct puffs_framebuf *pb,
+    const struct vattr *vap, const char *filename, enum vtype vt)
 {
+	struct puffs9p *p9p = puffs_getspecific(pu);
 	struct vattr fakeva;
 	uint32_t mode, atime, mtime;
 	uint64_t flen;
@@ -324,6 +333,12 @@
 	p9pbuf_put_str(pb, owner);
 	p9pbuf_put_str(pb, group);
 	p9pbuf_put_str(pb, "");			/* muid		*/
+	if (p9p->protover == P9PROTO_VERSION_U) {
+		p9pbuf_put_str(pb, P9PROTO_STAT_NOSTR);	/* extentions[s] */
+		p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4);	/* n_uid[4] */
+		p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4);	/* n_gid[4] */
+		p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4);	/* n_muid[4] */
+	}
 
 	curoff = puffs_framebuf_telloff(pb);
 	puffs_framebuf_seekset(pb, startoff);
@@ -352,7 +367,8 @@
 }
 
 int
-proto_expect_stat(struct puffs_framebuf *pb, struct vattr *va)
+proto_expect_stat(struct puffs_usermount *pu, struct puffs_framebuf *pb,
+    struct vattr *va)
 {
 	uint16_t dummy;
 	int rv;
@@ -361,5 +377,5 @@
 		return EPROTO;
 	if ((rv = p9pbuf_get_2(pb, &dummy)))
 		return rv;
-	return proto_getstat(pb, va, NULL, NULL);
+	return proto_getstat(pu, pb, va, NULL, NULL);
 }
--- a/usr.sbin/puffs/mount_9p/nineproto.h	Fri May 17 08:26:20 2019 +0000
+++ b/usr.sbin/puffs/mount_9p/nineproto.h	Fri May 17 08:48:04 2019 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nineproto.h,v 1.1 2007/04/21 14:21:43 pooka Exp $	*/
+/*	$NetBSD: nineproto.h,v 1.2 2019/05/17 08:48:04 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
@@ -30,7 +30,12 @@
 
 #include <stdint.h>
 
-#define P9PROTO_VERSION		"9P2000"
+#define P9PROTO_VERSION		0
+#define P9PROTO_VERSION_U	1
+
+#define P9PROTO_VERSTR		"9P2000"
+#define P9PROTO_VERSTR_U	"9P2000.u"
+#define P9PROTO_VERSTR_MAXLEN	(sizeof(P9PROTO_VERSTR_U))
 
 #define P9PROTO_T_VERSION	100
 #define P9PROTO_R_VERSION	101
@@ -66,12 +71,18 @@
 #define P9PROTO_NOFID		(uint32_t)~0
 #define P9PROTO_NOTAG		(uint16_t)~0
 
+#define P9PROTO_NUNAME_UNSPECIFIED	(uint16_t)~0
+
 /* type field in a qid */
 #define P9PROTO_QID_TYPE_DIR	0x80
 #define P9PROTO_QID_TYPE_APPEND	0x40
 #define P9PROTO_QID_TYPE_EXCL	0x20
 #define P9PROTO_QID_TYPE_MOUNT	0x10
 #define P9PROTO_QID_TYPE_AUTH	0x08
+/* P92000.u extensions */
+#define P9PROTO_QID_TYPE_TMP	0x04
+#define P9PROTO_QID_TYPE_LINK	0x02
+#define P9PROTO_QID_TYPE_FILE	0x00
 
 /* mode in open */
 #define P9PROTO_OMODE_READ	0x00
@@ -83,11 +94,24 @@
 
 /* for creating directories */
 #define P9PROTO_CPERM_DIR	0x80000000
+#define P9PROTO_CPERM_APPEND	0x40000000
+#define P9PROTO_CPERM_EXCL	0x20000000
+#define P9PROTO_CPERM_MOUNT	0x10000000
+#define P9PROTO_CPERM_AUTH	0x08000000
+#define P9PROTO_CPERM_TMP	0x04000000
+#define P9PROTO_CPERM_SYMLINK	0x02000000
+/* P92000.u extensions */
+#define P9PROTO_CPERM_DEVICE	0x00800000
+#define P9PROTO_CPERM_NAMEDPIPE	0x00200000
+#define P9PROTO_CPERM_SOCKET	0x00100000
+#define P9PROTO_CPERM_SETUID	0x00080000
+#define P9PROTO_CPERM_SETGID	0x00040000
 
 /* stat non-values */
 #define P9PROTO_STAT_NOVAL1	(uint8_t)~0
 #define P9PROTO_STAT_NOVAL2	(uint16_t)~0
 #define P9PROTO_STAT_NOVAL4	(uint32_t)~0
 #define P9PROTO_STAT_NOVAL8	(uint64_t)~0
+#define P9PROTO_STAT_NOSTR	""
 
 #endif /* PUFFS9P_PROTO_H_ */
--- a/usr.sbin/puffs/mount_9p/ninepuffs.c	Fri May 17 08:26:20 2019 +0000
+++ b/usr.sbin/puffs/mount_9p/ninepuffs.c	Fri May 17 08:48:04 2019 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: ninepuffs.c,v 1.24 2011/08/31 13:32:39 joerg Exp $	*/
+/*	$NetBSD: ninepuffs.c,v 1.25 2019/05/17 08:48:04 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ninepuffs.c,v 1.24 2011/08/31 13:32:39 joerg Exp $");
+__RCSID("$NetBSD: ninepuffs.c,v 1.25 2019/05/17 08:48:04 ozaki-r Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -50,6 +50,7 @@
 #include <unistd.h>
 
 #include "ninepuffs.h"
+#include "nineproto.h"
 
 #define DEFPORT_9P 564
 
@@ -107,6 +108,7 @@
 	unsigned short port;
 	int mntflags, pflags, ch;
 	int detach;
+	int protover = P9PROTO_VERSION;
 
 	setprogname(argv[0]);
 
@@ -117,7 +119,7 @@
 	detach = 1;
 	port = DEFPORT_9P;
 
-	while ((ch = getopt(argc, argv, "o:p:s")) != -1) {
+	while ((ch = getopt(argc, argv, "o:p:su")) != -1) {
 		switch (ch) {
 		case 'o':
 			mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags);
@@ -131,6 +133,9 @@
 		case 's':
 			detach = 0;
 			break;
+		case 'u':
+			protover = P9PROTO_VERSION_U;
+			break;
 		default:
 			usage();
 			/*NOTREACHED*/
@@ -177,6 +182,7 @@
 	memset(&p9p, 0, sizeof(p9p));
 	p9p.maxreq = P9P_DEFREQLEN;
 	p9p.nextfid = 1;
+	p9p.protover = protover;
 
 	/* user@ */
 	if ((p = strchr(argv[0], '@')) != NULL) {
--- a/usr.sbin/puffs/mount_9p/ninepuffs.h	Fri May 17 08:26:20 2019 +0000
+++ b/usr.sbin/puffs/mount_9p/ninepuffs.h	Fri May 17 08:48:04 2019 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: ninepuffs.h,v 1.12 2007/11/30 19:02:38 pooka Exp $	*/
+/*	$NetBSD: ninepuffs.h,v 1.13 2019/05/17 08:48:04 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
@@ -103,6 +103,8 @@
 	p9pfid_t nextfid;
 
 	size_t maxreq;		/* negotiated with server */
+
+	int protover;
 };
 
 struct dirfid {
@@ -147,18 +149,19 @@
 uint16_t	p9pbuf_get_tag(struct puffs_framebuf *);
 
 int	proto_getqid(struct puffs_framebuf *, struct qid9p *);
-int	proto_getstat(struct puffs_framebuf *, struct vattr *,
+int	proto_getstat(struct puffs_usermount *, struct puffs_framebuf *, struct vattr *,
 		      char **, uint16_t *);
 int	proto_expect_walk_nqids(struct puffs_framebuf *, uint16_t *);
-int	proto_expect_stat(struct puffs_framebuf *, struct vattr *);
+int	proto_expect_stat(struct puffs_usermount *, struct puffs_framebuf *,
+	                  struct vattr *);
 int	proto_expect_qid(struct puffs_framebuf *, uint8_t, struct qid9p *);
 
 int	proto_cc_dupfid(struct puffs_usermount *, p9pfid_t, p9pfid_t);
 int	proto_cc_clunkfid(struct puffs_usermount *, p9pfid_t, int);
 int	proto_cc_open(struct puffs_usermount *, p9pfid_t, p9pfid_t, int);
 
-void	proto_make_stat(struct puffs_framebuf *, const struct vattr *,
-			const char *, enum vtype);
+void	proto_make_stat(struct puffs_usermount *, struct puffs_framebuf *,
+	                const struct vattr *, const char *, enum vtype);
 
 struct puffs_node	*p9p_handshake(struct puffs_usermount *,
 				       const char *, const char *);
--- a/usr.sbin/puffs/mount_9p/node.c	Fri May 17 08:26:20 2019 +0000
+++ b/usr.sbin/puffs/mount_9p/node.c	Fri May 17 08:48:04 2019 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: node.c,v 1.21 2009/01/18 10:10:47 lukem Exp $	*/
+/*	$NetBSD: node.c,v 1.22 2019/05/17 08:48:04 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: node.c,v 1.21 2009/01/18 10:10:47 lukem Exp $");
+__RCSID("$NetBSD: node.c,v 1.22 2019/05/17 08:48:04 ozaki-r Exp $");
 #endif /* !lint */
 
 #include <assert.h>
@@ -62,7 +62,7 @@
 	p9pbuf_put_4(pb, p9n->fid_base);
 	GETRESPONSE(pb);
 
-	rv = proto_expect_stat(pb, vap);
+	rv = proto_expect_stat(pu, pb, vap);
 
  out:
 	RETURN(rv);
@@ -120,7 +120,7 @@
 	p9pbuf_put_2(pb, tag);
 	p9pbuf_put_4(pb, tfid);
 	GETRESPONSE(pb);
-	if ((rv = proto_expect_stat(pb, &va)) != 0) {
+	if ((rv = proto_expect_stat(pu, pb, &va)) != 0) {
 		proto_cc_clunkfid(pu, tfid, 0);
 		rv = ENOENT;
 		goto out;
@@ -194,7 +194,7 @@
 	}
 
 	while (count > 0) {
-		if ((rv = proto_getstat(pb, &va, &name, &statsize))) {
+		if ((rv = proto_getstat(pu, pb, &va, &name, &statsize))) {
 			/*
 			 * If there was an error, it's unlikely we'll be
 			 * coming back, so just nuke the dfp.  If we do
@@ -231,7 +231,7 @@
 	p9pbuf_put_1(pb, P9PROTO_T_WSTAT);
 	p9pbuf_put_2(pb, tag);
 	p9pbuf_put_4(pb, p9n->fid_base);
-	proto_make_stat(pb, va, NULL, pn->pn_va.va_type);
+	proto_make_stat(pu, pb, va, NULL, pn->pn_va.va_type);
 	GETRESPONSE(pb);
 
 	if (p9pbuf_get_type(pb) != P9PROTO_R_WSTAT)
@@ -426,6 +426,8 @@
 	p9pbuf_put_str(pb, name);
 	p9pbuf_put_4(pb, dirbit | (vap->va_mode & 0777));
 	p9pbuf_put_1(pb, 0);
+	if (p9p->protover == P9PROTO_VERSION_U)
+		p9pbuf_put_str(pb, ""); /* extension[s] */
 	GETRESPONSE(pb);
 
 	rv = proto_expect_qid(pb, P9PROTO_R_CREATE, &nqid);
@@ -579,7 +581,7 @@
 	p9pbuf_put_1(pb, P9PROTO_T_WSTAT);
 	p9pbuf_put_2(pb, tag);
 	p9pbuf_put_4(pb, p9n_src->fid_base);
-	proto_make_stat(pb, NULL, pcn_targ->pcn_name, pn_src->pn_va.va_type);
+	proto_make_stat(pu, pb, NULL, pcn_targ->pcn_name, pn_src->pn_va.va_type);
 	GETRESPONSE(pb);
 
 	if (p9pbuf_get_type(pb) != P9PROTO_R_WSTAT)